Entry Unique to User - django

I have a model that keeps track of websites, and want it to be unique to that user. For example if the site is google.com, the user can only enter it once, however still allow multiple users can enter google.com. To give you a better idea here is my models.py:
class Site(models.Model):
url = models.CharField(max_length=500)
tag = models.ForeignKey(Tag)
user = models.ForeignKey('customauth.UserProfile')
Is there anyway to make the url field unique to users?

You could use unique_together constraint,
class Site(models.Model):
url = models.CharField(max_length=500)
tag = models.ForeignKey(Tag)
user = models.ForeignKey('customauth.UserProfile')
class Meta:
unique_together = ('url', 'user')
This option allows a user to create a unique url, else django raises an error. A single user cannot create two objects with same url.
The ValidationError raised during model validation when the constraint is violated has the unique_together error code.

Related

How to get the first record of a 1-N relationship from the main table with Django ORM?

I have a Users table which is FK to a table called Post. How can I get only the last Post that the user registered? The intention is to return a list of users with the last registered post, but when obtaining the users, if the user has 3 posts, the user is repeated 3 times. I'm interested in only having the user once. Is there an alternative that is not unique?
class User(models.Model):
name = models.CharField(max_length=50)
class Post(models.Model):
title = models.CharField(max_length=50)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts', related_query_name='posts')
created = models.DateTimeField(default=timezone.now)
class Meta:
get_latest_by = 'created'
ordering = ['-created']`
I already tried with selected_related and prefetch_related, I keep getting multiple user registrations when they have multiple Posts.
user = User.objects.select_related('posts').all().values_list('id', 'name', 'posts__title', 'posts__created')
This does give me the answer I want, but when I change the created field to sort by date, I don't get the newest record, I always get the oldest.
user = User.objects.select_related('posts').all().values_list('id', 'name', 'posts__title', 'posts__created').distinct('id')
I'm trying to do it without resorting to doing a record-by-record for and getting the most recent Post. I know that this is an alternative but I'm trying to find a way to do it directly with the Django ORM, since there are thousands of records and a for is less than optimal.
In that case your Django ORM query would first filter posts by user then order by created in descending order and get the first element of the queryset.
last_user_post = Post.objects.filter(user__id=1).order_by('-created').first()
Alternatively, you can use an user instance:
user = User.objects.get(id=1)
last_user_post = Post.objects.filter(user=user).order_by('-created').first()

Display User's 'is_active' status in TabularInline Django

I have a Client object that has a User and a Company objects as FKs
class Client(models.Model):
user = models.OneToOneField(User)
company = models.ForeignKey(Company, blank=True, null=True)
In my CompanyAdmin, I want a list of all clients as a TabularInline, including the active status of each client (based on user object)
class CompanyClients(admin.TabularInline):
model = Client
fields = ('user', 'master')
class CompanyAdmin(admin.ModelAdmin):
inlines = [CompanyClients]
I want to add a column in my TabularInline to indicate that that user is active or not. I tried using 'user__is_active' to my fields but I get this error:
Unknown field(s) (user__is_active) specified for Client
I just want an indication even if read-only (which I tried by putting a readonly_fields and it didn't work too), not looking to save/edit each client user's active status value from the Tabular form.
How can I approach this? Thanks in advance.
class CompanyClients(admin.TabularInline):
model = Client
fields = ('user', 'master','user__active)
user__active

Force model fields in Django

When creating a model in Django like this example:
class Musician(models.Model):
first_name = models.CharField(max_length=50, primary_key=True)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100)
I noticed some problem (not sure if that's best word) with this approach. There is nothing preventing you from creating something like:
musician = Musician()
musician.save()
effectively having primary_key value equal to None. I would like to force user to set first_name, but frankly speaking I cannot find any simple solution for that.
Is there a way to achieve this?
First of all, don't set first_name as primary key. Just leave the default primary key as the id field. A primary key needs to be unique (a first_name isn't) and should not be something a user enters.
Second, it's true that you cannot enforce a CharField to not be empty at the database level. But you can enforce it at the code level, so that anytime you create a Django Form and validate it, it will raise an error.
In fact, Django does it automatically for you, in your case. By default first_name is a required field, since you didn't set blank=True.
So if you do:
musician = Musician()
musician.full_clean()
this raises a ValidationError.
If you create a form for your model (which is what you need if you want users to create a Musician):
class MusicianForm(ModelForm):
class Meta:
model = Musician
fields = '__all__'
form = MusicianForm(data={})
form.instance.first_name
# ''
form.is_valid()
# False
form.save()
# ValueError: The Musician could not be created because the data didn't validate.
You'll also see that if you register Musician in admin.py for django admin site, you can't leave any of the fields empty. It just won't save.

Django Filter ForeignKey relationships in get_queryset

I wonder what to do here.
So I have an EmailAddress class which has a ForeignKey relationship to my User class
class EmailAddress(models.Model):
user = models.ForeignKey(allauth_app_settings.USER_MODEL, verbose_name=_('user'))
email = models.EmailField(unique=app_settings.UNIQUE_EMAIL,
verbose_name=_('e-mail address'))
I also have a UserProfile class which has a OneToOneField relationship with the mentioned User like so:
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile')
attribute= models.CharField("attr", max_length=150, blank=False)
Now in admin.py I want to filter the Users so that the current user who is logged in to admintool can only see emails from users who share some attribute. The catch is that the attribute is saved in UserProfile and I need to get there through the email.
Basically I don't know how to access the 'attribute' which is in the UserProfile. I understand that I want to filter users by taking the email finding the user that this email belongs to and then compare his 'attribute' to the user who send the request to decide whether to show it to him or not.
def get_queryset(self, request):
user = [User whos email is in the list]
qs = [the queryset]
[and then]
return qs.filter([filter so the user attribute = the request.user attribute])
Im using allauth btw. in case you wonder what
allauth_app_settings.USER_Model
stands for.
Have a nice day!
You need to use the double-underscore syntax to follow the relationships.
qs.filter(user__userprofile__attribute=request.user.attribute)

Django :Suggestion for django model

I am using django models to create my database .
here is my User Class
class User(models.Model):
user_name = models.CharField(max_length=100,null = False)
first_name = models.CharField(max_length=100)
middle_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
tags = here what to do ?
now i am planning to add tags for User so that user can select the tags (it can be more then one also )
Here is my Tags Class
Class Tags(models.Model)
tag = models.CharField()
my question is which relation should i use for the reference Tags from User table (Foreign key or Manytomany )
Note: In future i will search the users based on tags so please suggest me the better way to do this
Use a ManytoMany relationship: different users may use the same tags and a single User will have several tags:
tags= models.ManyToManyField(Tags, verbose_name="list of tags")
Anyway, you don't have to implement a Model for the User, there is a User model that comes with django. See the docs:
Django docs
Django book