Пример #1
0
class ProductImage(models.Model):
    image = VersatileImageField('', upload_to='product', blank=True, null=True)
    product = models.ForeignKey(Product, on_delete=models.CASCADE)

    def update(self):
        self.save()

    @property
    def thumbnail_url(self):
        if self.image and hasattr(self.image, 'url'):
            return self.image.thumbnail['600x600'].url

    @property
    def thumbnail_100_url(self):
        if self.image and hasattr(self.image, 'url'):
            return self.image.thumbnail['100x100'].url
Пример #2
0
class Image(TimeStampedModel):
    product = models.ForeignKey('products.Product', null=False, blank=False)
    title = models.CharField(max_length=2048, null=True, blank=True)
    description = models.CharField(max_length=2048, null=True, blank=True)
    featured = models.BooleanField(default=False)
    file = VersatileImageField(
        upload_to='images/product', max_length=255, null=False, blank=False,
        ppoi_field='image_ppoi' # Image Primary Point of Interest (PPOI)
    )
    image_ppoi = PPOIField()

    def __str__(self):
        return self.title if self.title else self.file.url

    class Meta:
        get_latest_by = 'modified'
Пример #3
0
class Photo(models.Model):
    class Meta:
        ordering = ['item_order']

    gallery = models.ForeignKey(Gallery)

    description = models.CharField(_('Description'), max_length=60)

    item_order = models.PositiveIntegerField(default=0,
                                             blank=False,
                                             null=False)

    image = VersatileImageField(
        _('Photo'),
        upload_to=image_path,
    )
Пример #4
0
class SkillImage(SortableModel):
    skill_type = models.ForeignKey(SkillType,
                                   related_name='images',
                                   on_delete=models.CASCADE)
    image = VersatileImageField(upload_to='skills',
                                ppoi_field='ppoi',
                                blank=False)
    ppoi = PPOIField()
    alt = models.CharField(max_length=128, blank=True)

    class Meta:
        ordering = ('sort_order', )
        app_label = 'skill'

    def get_ordering_queryset(self):
        return self.skill_type.images.all()
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)
Пример #6
0
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)
Пример #7
0
class CampaignImage(SortableModel):
    campaign = models.ForeignKey(Campaign,
                                 related_name="images",
                                 on_delete=models.CASCADE)
    alt = models.CharField(max_length=128, blank=True)

    image = VersatileImageField('image',
                                upload_to='campaigns',
                                default='placeholder1080x1080.png')

    class Meta:
        ordering = ("sort_order", )
        app_label = "campaign"

    def get_ordering_queryset(self):
        return self.campaign.images.all()
Пример #8
0
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", "pk")
        app_label = "product"

    def get_ordering_queryset(self):
        return self.product.images.all()
Пример #9
0
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
Пример #10
0
class Photo(BaseModel):
    album = models.ForeignKey(Album)
    title = models.CharField(max_length=30)
    description = models.TextField(blank=True)
    owner = models.ForeignKey(settings.AUTH_USER_MODEL)
    img = VersatileImageField('Image', upload_to='photo/')
    like_users = models.ManyToManyField(settings.AUTH_USER_MODEL,
                                        through='PhotoLike',
                                        related_name='photo_set_like_users')
    dislike_users = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        through='PhotoDislike',
        related_name='photo_set_dislike_users')

    def __str__(self):
        return self.title
Пример #11
0
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
Пример #12
0
class Disertante(models.Model):
    nombre = models.CharField(max_length=80)
    bio = models.TextField(null=True, blank=True)
    pic = VersatileImageField(upload_to='users/pics', null=True, blank=True)
    spinq_user_admin = models.ForeignKey(
        SpinqUser,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        help_text='Usuario que administra el perfil')

    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.nombre
Пример #13
0
class ImageData(SortableModel):
    name = models.CharField('Name', max_length=80)
    image = VersatileImageField(upload_to='medias',
                                ppoi_field='ppoi',
                                blank=False)
    height = models.PositiveIntegerField('Image Height', blank=True, null=True)
    width = models.PositiveIntegerField('Image Width', blank=True, null=True)
    ppoi = PPOIField("Image PPOI")

    class Meta:
        ordering = ('sort_order', )
        verbose_name = 'Image Example'
        verbose_name_plural = 'Image Examples'

    def get_ordering_queryset(self):
        return ImageData.objects.all()
Пример #14
0
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)
Пример #15
0
class Profile(models.Model):
    """
    User profile to handle extra fields as per requirement
    """
    user = models.OneToOneField(User,
                                related_name='profile',
                                on_delete=models.CASCADE)
    access_type = models.PositiveIntegerField(choices=ACCESS_TYPE, default=5)
    mobile = models.CharField(max_length=15, null=True, blank=True)
    profile_pic = VersatileImageField(null=True, blank=True, max_length=500)
    age = models.IntegerField(null=True, blank=True)
    position = models.CharField(max_length=256, null=True, blank=True)
    about_me = models.TextField(null=True, blank=True)

    def __str__(self):
        return self.user.username
Пример #16
0
class serie(models.Model):
    name = models.CharField(max_length=100)
    actors = models.ManyToManyField(actor)
    pic = VersatileImageField('Image',
                              upload_to='series/%Y-%m-%d',
                              ppoi_field='series_ppoi')
    series_ppoi = PPOIField()
    release = models.DateField()
    review = models.TextField()
    seasons = models.IntegerField()
    owner = models.ForeignKey(User,
                              related_name='series',
                              on_delete=models.CASCADE)

    def __unicode__(self):
        return '%s' % (self.name)
Пример #17
0
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
Пример #18
0
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
Пример #19
0
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']
Пример #20
0
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)
Пример #21
0
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)
Пример #22
0
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
Пример #23
0
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)
Пример #24
0
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
    )
Пример #25
0
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
Пример #26
0
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"), )
Пример #27
0
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
Пример #28
0
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')
Пример #29
0
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
Пример #30
0
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())