class Image(models.Model): image = VersatileImageField('Image', upload_to="images/", ppoi_field='image_ppoi') caption = models.TextField(max_length=100) title = models.CharField(max_length=100, default="Untitled") likes = models.IntegerField(default=0) shares = models.IntegerField(default=0) private = models.BooleanField(default=False) profile_picture = models.BooleanField(default=False) timestamp = models.DateTimeField(auto_now_add=True) image_ppoi = PPOIField() owner = models.ForeignKey(User, related_name='images', on_delete=models.CASCADE, null=True)
class Recipe(models.Model): user = models.ForeignKey(User, related_name='recipes') title = models.CharField(max_length=100) description = models.TextField(blank=True, null=True) img = VersatileImageField(upload_to='recipes/') public = models.BooleanField(default=True) favorites = models.ManyToManyField(User, related_name='favorites', blank=True) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) def is_favorited(self, user): return user.id in self.favorites.values_list('id', flat=True)
class Show(TimeStampedModel): name = models.CharField(max_length=256) position = models.IntegerField() image = VersatileImageField( 'Image', blank=True, upload_to='images', ppoi_field='ppoi', ) ppoi = PPOIField('Image PPOI') class Meta: ordering = ('position', ) def __str__(self): return 'Show (Position: {}): {}'.format(self.position, self.name)
class ProductImage(SortableModel): product = models.ForeignKey(Product, related_name="images", on_delete=models.CASCADE) image = VersatileImageField(upload_to="products", ppoi_field="ppoi", blank=False) ppoi = PPOIField() alt = models.CharField(max_length=128, blank=True) class Meta: ordering = ("sort_order", ) app_label = "product" def get_ordering_queryset(self): return self.product.images.all()
class Benefit(models.Model): name = models.CharField(max_length=32, ) text = models.TextField() image = VersatileImageField() is_active = models.BooleanField(default=False, ) translated = TranslationProxy() class Meta: permissions = (( 'manage_benefits', pgettext_lazy('Permission description', 'Administrar beneficios.'), ), ) def __str__(self): return self.name
class AttributeChoiceValue(models.Model): display = models.CharField( pgettext_lazy('Attribute choice value field', 'display name'), max_length=100) color = models.CharField( pgettext_lazy('Attribute choice value field', 'color'), max_length=7, validators=[RegexValidator('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')], blank=True) image = VersatileImageField( pgettext_lazy('Attribute choice value field', 'image'), upload_to='attributes', blank=True, null=True) attribute = models.ForeignKey(ProductAttribute, related_name='values') def __str__(self): return self.display
class Senate(models.Model): # Validators valid_year = RegexValidator(r'^[0-9]{4}$', message='Not a valid year!') # Model name = models.CharField(max_length=128) description = RichTextUploadingField(blank=True) cover = VersatileImageField('Cover', upload_to='society_%Y', help_text="Upload high quality picture") skin = models.CharField( max_length=32, choices=SKIN_CHOICES, blank=True, default='mdb-skin', help_text="Choose a skin while displaying senate page.") members = models.ManyToManyField(UserProfile, through='SenateMembership', through_fields=('senate', 'userprofile')) coordinator_student = models.ForeignKey(FacultyAdvisor, blank=True, null=True, default=None, on_delete=models.SET_NULL) report_link = models.URLField( help_text='Add a drive link to show on senate page', null=True, blank=True) custom_html = models.TextField( blank=True, null=True, default=None, help_text="Add custom HTML to view on society page.") slug = models.SlugField(unique=True, help_text="This will be used as URL. /senate/slug") is_active = models.BooleanField(default=False) year = models.CharField(max_length=4, choices=YEAR_CHOICES, validators=[valid_year]) class Meta: ordering = ["-id"] def get_absolute_url(self): return reverse('main:senate-detail', kwargs={'slug': self.slug}) def __str__(self): return self.name + ' - ' + self.year
class Partner(TranslatableModel): '''Model for partners of the TEDxNTUA organization. The `partner_type` attribute is represented as a CharField with limited possible values. The definition follows the official documentation example: https://docs.djangoproject.com/en/2.2/ref/models/fields/#choices The `link` attribute is represented as a URLField. The definition follows the official documentation example: https://docs.djangoproject.com/en/2.2/ref/models/fields/#urlfield ''' GRAND_SPONSORS = 'GS' GRAND_CARRIER_SPONSORS = 'GCS' GRAND_HOSPITALITY_SPONSORS = 'GHS' SPONSORS = 'SPO' SUPPORTERS = 'SUP' MEDIA_PARTNERS = 'MP' COMMUNITY_PARTNERS = 'CP' PARTNER_TYPES = ( (GRAND_SPONSORS, _('Grand Sponsors')), (GRAND_CARRIER_SPONSORS, _('Grand Carrier Sponsors')), (GRAND_HOSPITALITY_SPONSORS, _('Grand Hospitality Sponsors')), (SPONSORS, _('Sponsors')), (SUPPORTERS, _('Supporters')), (MEDIA_PARTNERS, _('Media Partners')), (COMMUNITY_PARTNERS, _('Community Partners')), ) translations = TranslatedFields( name=models.CharField(max_length=255, verbose_name='name')) partner_type = models.CharField(max_length=3, choices=PARTNER_TYPES) link = models.URLField() image = VersatileImageField('Image', upload_to='partners/', width_field='image_width', height_field='image_height') image_height = models.PositiveIntegerField(editable=False, null=True) image_width = models.PositiveIntegerField(editable=False, null=True) is_published = models.BooleanField(_('Published'), default=True) leaflet = models.FileField(upload_to='partners/leaflet/', ) objects = PartnerManager() def __str__(self): return self.name
class Presenter(TranslatableModel): ''' Person that participates in the event as a guest, ie. a speaker, a performer, a workshop presenter or a host. First and last name are the only required fields. ''' translations = TranslatedFields( name=models.CharField(max_length=255, default=''), occupation=models.CharField(max_length=255, blank=True), short_bio=models.TextField(blank=True, verbose_name='Short bio'), quote=models.CharField(max_length=255, blank=True, verbose_name='Inspirational quote')) link = models.URLField(blank=True, verbose_name='Website or social media profile') image = VersatileImageField( 'Image', upload_to='presenters/', width_field='image_width', height_field='image_height', null=True, blank=True, ) image_height = models.PositiveIntegerField(editable=False, null=True) image_width = models.PositiveIntegerField(editable=False, null=True) is_published = models.BooleanField(_('Published'), default=True) # Managers are an easy way to create custom filters for queries. # # Documentation link: # https://docs.djangoproject.com/en/2.2/topics/db/managers/ objects = TranslatableManager() speakers = PresenterTypeManager(Activity.TALK) performers = PresenterTypeManager(Activity.PERFORMANCE) side_presenters = PresenterTypeManager(Activity.SIDE_EVENT) hosts = PresenterTypeManager(Activity.HOSTING) slug = EnglishAutoSlugField(populate_from=['name'], overwrite=True) def __str__(self): return self.name
class User(PermissionsMixin, ModelWithMetadata, AbstractBaseUser): email = models.EmailField(unique=True) first_name = models.CharField(max_length=256, blank=True) last_name = models.CharField(max_length=256, blank=True) phone = models.CharField(max_length=25, blank=True) addresses = models.ManyToManyField( Address, blank=True, related_name="user_addresses" ) is_staff = models.BooleanField(default=False) is_active = models.BooleanField(default=True) note = models.TextField(null=True, blank=True) date_joined = models.DateTimeField(default=timezone.now, editable=False) default_shipping_address = models.ForeignKey( Address, related_name="+", null=True, blank=True, on_delete=models.SET_NULL ) default_billing_address = models.ForeignKey( Address, related_name="+", null=True, blank=True, on_delete=models.SET_NULL ) avatar = VersatileImageField(upload_to="user-avatars", blank=True, null=True) USERNAME_FIELD = "email" objects = UserManager() class Meta: permissions = ( (AccountPermissions.MANAGE_USERS.codename, "Manage customers."), (AccountPermissions.MANAGE_STAFF.codename, "Manage staff."), ) def get_full_name(self): if self.first_name or self.last_name: return ("%s %s" % (self.first_name, self.last_name)).strip() if self.default_billing_address: first_name = self.default_billing_address.first_name last_name = self.default_billing_address.last_name if first_name or last_name: return ("%s %s" % (first_name, last_name)).strip() return self.email def get_short_name(self): return self.email def has_perm(self, perm: BasePermissionEnum, obj=None): # type: ignore # This method is overridden to accept perm as BasePermissionEnum return super().has_perm(perm.value, obj)
class Patient(CommonInfo): id = models.AutoField(primary_key=True) last_name = models.CharField(max_length=25, db_index=True) first_name = models.CharField(max_length=25, db_index=True) middle_initial = models.CharField(max_length=1, blank=True, null=True) age = models.IntegerField(blank=False, null=False, editable=False, default=1) contact_num = models.CharField(max_length=15, blank=True, null=True) address = models.CharField(max_length=50, blank=True, null=True) town = models.ForeignKey('Town', blank=False, null=False, default=None, on_delete=models.SET_DEFAULT) date_of_birth = models.DateField(("Date of birth"), default=datetime.date.today) #pic = models.ImageField(blank=True, null=True) pat_pic = VersatileImageField('Pat_Pic', upload_to='images') occupation = models.ForeignKey(Occupation, blank=True, null=True, default=None, on_delete=models.SET_DEFAULT) email = models.EmailField(blank=True, null=True) GENDER = ( ('F', 'Female'), ('M', 'Male'), ) gender = models.CharField(max_length=1, choices=GENDER, blank=False, null=False, default='F', help_text='Select Gender') class Meta: ordering = ['last_name', 'first_name'] def get_absolute_url(self): return reverse('patient-detail', args=[str(pat.id)]) def __str__(self): return '%s, %s' % (self.last_name, self.first_name)
class Album(models.Model): name = models.CharField(max_length=255, null=False, blank=False, verbose_name='Название') description = models.TextField(null=True, blank=True, verbose_name='Описание') created_at = models.DateTimeField(auto_now=True, null=False, blank=True, verbose_name='Созданно') main_image = VersatileImageField(upload_to=album_upload_location, null=False, blank=False, verbose_name='Фото') event = models.ForeignKey(Event, related_name='album', null=False, blank=False, verbose_name='Мероприятие') objects = models.Manager() related_objects = GalleryManager() def __str__(self): return self.name class Meta: verbose_name = 'Альбом' verbose_name_plural = 'Альбомы' ordering = ['-created_at']
class Patient(models.Model): first_name = models.TextField(verbose_name='Encrypted first name') last_name = models.TextField(verbose_name='Encrypted last name') date_of_birth = models.TextField(verbose_name='Encrypted date of birth', blank=True, null=True) mrn = models.TextField(null=True, blank=True, verbose_name='Encrypted Medical Record Number') mrn_hash = models.CharField(max_length=32, unique=True, null=True, blank=True, verbose_name='Medical Record Number') photo = VersatileImageField(verbose_name='Profile Picture', upload_to=patient_photo_path, storage=private_storage, max_length=300, null=True, blank=True) sex = models.CharField(max_length=1, choices=SexEnum.CHOICES, verbose_name='Sex', blank=True, null=True) race = models.SmallIntegerField(choices=RaceEnum.CHOICES, verbose_name='Race', blank=True, null=True) doctors = models.ManyToManyField(Doctor, related_name="patients", through='DoctorToPatient') objects = PatientQuerySet.as_manager() class Meta: verbose_name = 'Patient' verbose_name_plural = 'Patients' @property def valid_consent(self): return self.consents.valid().first() def __str__(self): return "Patient: {0} ({1},{2})".format(self.pk, self.get_race_display(), self.get_sex_display())
class Room(models.Model): creator = models.ForeignKey(User, related_name='creator', on_delete=models.CASCADE, null=True) title = models.CharField(unique=True, max_length=40) summary = models.CharField(max_length=300, default='Summarize me!') content = models.CharField(max_length=700, default='Some Content!') date_posted = models.DateTimeField(default=datetime.now, blank=True) Private = 'Private' Public = 'Public' Protected = 'Protected' security_categories = ( (Public, 'Public'), (Private, 'Private'), (Protected, 'Protected'), ) security = models.CharField(choices=security_categories, default='Public', max_length=10) Question = 'Question' Advice = 'Advice' Discussion = 'Discussion' type_categories = ( (Question, 'Question'), (Advice, 'Advice'), (Discussion, 'Discussion'), ) type = models.CharField(choices=type_categories, default='Question', max_length=15) category_categories = (('GS', 'General Software'), ('CC', 'Code Challenges'), ('D', 'Design (UI/UX)'), ('WD', 'Web Dev'), ('MD', 'Mobile Dev'), ('GD', 'Game Dev'), ('IT', 'Tech & IT'), ('AR', 'Art'), ('C', 'Casual'), ('AC', 'Academic'), ('O', 'Other')) categories = MultiSelectField(choices=category_categories, max_choices=3, default=['O']) members = models.PositiveIntegerField(default=0) likes = models.PositiveIntegerField(default=0) archived = models.BooleanField(default=False) room_image = VersatileImageField( default='room_pic_hashed/default_room_image.jpg', upload_to='room_pic_hashed')
class Face(models.Model): user = models.ForeignKey(User, verbose_name='usuario') person = models.ForeignKey(Person, verbose_name='sujeto') img = VersatileImageField(upload_to='img/face', verbose_name='face') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) faceid = models.CharField(max_length=60, blank=True) class Meta: verbose_name = 'Foto' verbose_name = 'Fotos' def __str__(self): return self.person.name def image_url(self): return self.img.url
class ImageAsset(ReprMixin, models.Model): created_at = models.DateTimeField(auto_now_add=True) created_by = models.ForeignKey( "users.Profile", related_name="images_files", on_delete=models.PROTECT, null=True, blank=True, ) file = VersatileImageField( upload_to="images/", width_field="width", height_field="height", ) height = models.PositiveIntegerField(blank=True, null=True) width = models.PositiveIntegerField(blank=True, null=True)
class ContentType(models.Model): name = models.CharField(max_length=160, unique=True) slug = models.CharField(max_length=160, unique=True) description = models.TextField(null=True) image = VersatileImageField('Path', upload_to=path_and_rename, ppoi_field='path_ppoi') path_ppoi = PPOIField() def delete(self, *args, **kwargs): # You have to prepare what you need before delete the model storage, path = self.image.storage, self.image.path # Delete the model before the file super(ContentType, self).delete(*args, **kwargs) # Delete the file after the model storage.delete(path) def __str__(self): return self.name
class Model(models.Model): name = models.CharField(max_length=255) slug = models.SlugField(editable=False, db_index=True) brand = models.ForeignKey(Brand, related_name='brand_models') picture = VersatileImageField(upload_to='phone/', blank=True, null=True, default='icons/default_phone.png') created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) repairing_request = models.PositiveIntegerField(default=0) repaired_items = models.PositiveIntegerField(default=0) unlocking_request = models.PositiveIntegerField(default=0) unlocked_items = models.PositiveIntegerField(default=0) repairing_request = models.PositiveIntegerField(default=0) repaired_items = models.PositiveIntegerField(default=0) # unlocking_request = models.PositiveIntegerField(default=0) # unlocked_items = models.PositiveIntegerField(default=0) flashing_request = models.PositiveIntegerField(default=0) flashed_items = models.PositiveIntegerField(default=0) satisfied_clients_count = models.PositiveIntegerField(default=0) def __str__(self): return unicode(self.name) def save(self, *args, **kwargs): self.slug = slugify(self.name) notify = kwargs.get('notify', None) if notify: if not Notification.objects.filter( model=self, notification_type=Notification.NEW_MODEL_ADDED).exists(): Notification(model=self, brand=self.brand, notification_type=Notification.NEW_MODEL_ADDED) super(Model, self).save(*args, **kwargs) class Meta: unique_together = (("name", "brand"), )
class StoreImage(SortableModel): store = models.ForeignKey(Store, related_name='images', on_delete=models.CASCADE) image = VersatileImageField(upload_to='stores', ppoi_field='ppoi', blank=False) ppoi = PPOIField() alt = models.CharField(max_length=128, blank=True) description = models.TextField() class Meta: ordering = ('sort_order', ) app_label = 'store' def get_ordering_queryset(self): return self.store.images.all()
class Category(MPTTModel): name = models.CharField(max_length=128) description = models.TextField(blank=True) parent = models.ForeignKey('self', null=True, blank=True, related_name='children', on_delete=models.CASCADE) background_image = VersatileImageField(upload_to='category-backgrounds', blank=True, null=True) objects = models.Manager() tree = TreeManager() def __str__(self): return self.name
class PostImage(models.Model): post = models.ForeignKey(Post, related_name='images', null=True, on_delete=models.SET_NULL) image = VersatileImageField( verbose_name='Image', upload_to='images/', width_field='width', height_field='height') caption = models.TextField(blank=True) height = models.PositiveIntegerField( 'Image Height', blank=True, null=True ) width = models.PositiveIntegerField( 'Image Width', blank=True, null=True )
class Category(MPTTModel): name = models.CharField(max_length=128) slug = models.SlugField(max_length=50) description = models.TextField(blank=True) parent = models.ForeignKey('self', null=True, blank=True, related_name='children', on_delete=models.CASCADE) objects = models.Manager() tree = TreeManager() image = VersatileImageField(upload_to='categories', blank=True) class Meta: app_label = 'product' permissions = (('view_category', pgettext_lazy('Permission description', 'Can view categories')), ('edit_category', pgettext_lazy('Permission description', 'Can edit categories'))) def __str__(self): return self.name @shared_task def create_category_thumbnails(self): CategoryWarmer(items=[self])() def get_absolute_url(self, ancestors=None): return reverse('product:category', kwargs={ 'path': self.get_full_path(ancestors), 'category_id': self.id }) def get_full_path(self, ancestors=None): if not self.parent_id: return self.slug if not ancestors: ancestors = self.get_ancestors() nodes = [node for node in ancestors] + [self] return '/'.join([node.slug for node in nodes])
class Presenter(models.Model): ''' Person that participates in the event as a guest, ie. a speaker, a performer, a workshop presenter or a host. First and last name are the only required fields. ''' first = models.CharField(max_length=255, verbose_name='First name') last = models.CharField(max_length=255, verbose_name='Last name') occupation = models.CharField(max_length=255, blank=True) short_bio = models.TextField(blank=True, verbose_name='Short bio') quote = models.CharField(max_length=255, blank=True, verbose_name='Inspirational quote') link = models.URLField(blank=True, verbose_name='Website or social media profile') image = VersatileImageField('Image', upload_to='static/', width_field='image_width', height_field='image_height') image_height = models.PositiveIntegerField(editable=False, null=True) image_width = models.PositiveIntegerField(editable=False, null=True) # Managers are an easy way to create custom filters for queries. # # If a models.Manager() is declared in a model, then the `objects` default manager # is discarded. We added it explicitly in case it comes in handy. # # Documentation link: # https://docs.djangoproject.com/el/2.1/topics/db/managers/ objects = models.Manager() speakers = PresenterTypeManager(Activity.TALK) performers = PresenterTypeManager(Activity.PERFORMANCE) workshop_presenters = PresenterTypeManager(Activity.WORKSHOP) @property def fullname(self): return ' '.join([self.first, self.last]) def __str__(self): return self.fullname
class AbstractProductSection(MPTTModel, AbstractProductBase): class Meta: abstract = True app_label = 'shop' ordering = ['sort'] verbose_name = _('product section') verbose_name_plural = _('product sections') unique_together = ['catalog', 'slug'] slug = AutoSlugField(_('URL'), populate_from='name', unique=True) image = VersatileImageField(_('Image'), upload_to='shop/section', null=True, blank=True) parent = TreeForeignKey('self', null=True, related_name='children', verbose_name=_('Parent Section'), blank=True, on_delete=models.PROTECT) catalog = models.ForeignKey('shop.ProductCatalog', verbose_name=_('Product catalog'), related_name='sections', on_delete=models.PROTECT) sort = models.IntegerField(default=1) def __str__(self): parent = self.parent section_names = [self.name] while parent: section_names.append(parent.name) parent = parent.parent return ' / '.join(reversed(section_names)) def serializable_object(self): obj = { 'pk': self.pk, 'parent_id': self.parent_id, 'name': self.name, 'is_visible': __('yes') if self.is_visible else __('no'), 'children': [] } for child in self.get_children(): obj['children'].append(child.serializable_object()) return obj
class CommonAccountDetails(CommonInfo): class Meta: abstract = True STATE_CHOICES = state_choices # first_name = models.CharField(_('first name'), max_length=30, null=True, # blank=True) # last_name = models.CharField(_('last name'), max_length=30, null=True, # blank=True) initial_password = models.CharField(max_length=40, null=True, blank=True) spouse_name = models.CharField(_('significant other'), max_length=30, null=True, blank=True) street_address = models.CharField(verbose_name=_('address'), max_length=100, null=True, blank=True) city = models.CharField(verbose_name=_('city'), max_length=100, null=True, blank=True) state = models.CharField(verbose_name=_('state'), max_length=40, choices=STATE_CHOICES, null=True, blank=True) zip_code = models.IntegerField(verbose_name=_('zip code'), null=True, blank=True) # main_phone = PhoneNumberField(verbose_name=_('main phone'), max_length=15, # blank=True) # alt_phone = PhoneNumberField(verbose_name=_('alternate phone (not required)'), # max_length=15, null=True, blank=True) image = VersatileImageField('Image', upload_to='images/staff/', null=True, blank=True, width_field='width', height_field='height', ppoi_field='ppoi') height = models.PositiveIntegerField('Image Height', blank=True, null=True) width = models.PositiveIntegerField('Image Width', blank=True, null=True) ppoi = PPOIField('Image PPOI')
class UserProfile(TimeStampedModel): """ """ user = models.OneToOneField(User, related_name='profile', on_delete=models.CASCADE) tag = models.CharField(max_length=120, blank=True, null=True) picture = VersatileImageField(upload_to='profile', blank=True, null=True) aboutme = models.TextField(blank=True, null=True, verbose_name="Profile Summary") phone = models.CharField(max_length=120, blank=True, null=True) location = models.CharField(max_length=250, blank=True, null=True) time_zone = TimeZoneField(default='Asia/Kolkata', null=True, blank=True) language = LanguageField(default='en') dob = models.DateField(null=True, blank=True) gender = models.PositiveSmallIntegerField(choices=GENDER) class Meta: ordering = ("-date_updated", ) def __str__(self): """ :return: """ return "Profile of {}".format(self.user.get_full_name()) @property def get_location(self): return "{}".format(self.location) def get_absolute_url(self): return reverse('user_profile', kwargs={'userid': self.user.username}) def get_screen_name(self): return "{}".format(self.user.get_full_name()) @property def get_picture(self): if not self.picture: self.picture = 'placeholder/no-image.png' self.save() return self.picture
class Set(models.Model): name = models.CharField(max_length=255, null=False, unique=True, blank=False, verbose_name='Название') description = models.TextField(null=False, blank=False, verbose_name='Описание') menu = models.ManyToManyField('Menu', through='MenuSet', related_name='menus', verbose_name='Позиции меню') created_at = models.DateTimeField(auto_now=True, null=False, blank=True, verbose_name='Созданно') photo = VersatileImageField(upload_to=set_upload_location, null=True, blank=True, verbose_name='Фото') photo_base64 = models.CharField(max_length=255, null=False, blank=True, default='base', verbose_name='Фото Base64') is_active = models.BooleanField(default=True, null=False, blank=True, verbose_name='Активированно') additional = ArrayField(base_field=models.CharField(max_length=128), null=True, blank=True, verbose_name='Дополнительные блюда') extra = JSONField(blank=True, null=True, default={}, verbose_name='Дополнительно') def __str__(self): return self.name class Meta: verbose_name = 'Набор' verbose_name_plural = 'Наборы'
class Category(ModelWithMetadata, MPTTModel, SeoModel): name = models.CharField(max_length=250) slug = models.SlugField(max_length=255, unique=True, allow_unicode=True) description = SanitizedJSONField(blank=True, null=True, sanitizer=clean_editor_js) parent = models.ForeignKey( "self", null=True, blank=True, related_name="children", on_delete=models.CASCADE ) background_image = VersatileImageField( upload_to="category-backgrounds", blank=True, null=True ) background_image_alt = models.CharField(max_length=128, blank=True) objects = models.Manager() tree = TreeManager() translated = TranslationProxy() def __str__(self) -> str: return self.name
class Collection(SeoModel): name = models.CharField(max_length=128, unique=True) slug = models.SlugField(max_length=128) products = models.ManyToManyField( Product, blank=True, related_name='collections') background_image = VersatileImageField( upload_to='collection-backgrounds', blank=True, null=True) class Meta: ordering = ['pk'] def __str__(self): return self.name def get_absolute_url(self): return reverse( 'product:collection', kwargs={'pk': self.id, 'slug': self.slug})
class Image(models.Model): tag = models.CharField(max_length=128) image = VersatileImageField(upload_to=file_path_name, ppoi_field='image_ppoi') image_ppoi = PPOIField() create_at = models.DateTimeField(auto_now_add=True) content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() content_object = GenericForeignKey('content_type', 'object_id') class Meta: db_table = 'image'