Django UserProfile slug field - django

I'm looking to create a url to visit a user profile using a slug. Ie. I want to visit /profile/myname to bring up my user profile. What I am having difficulties with is implementing the slug field for a user model.
Additionally, not sure if this matters or not but I have created a UserProfile model which extends the standard User model as shown below:
from django.contrib.auth.models import User
from autoslug import AutoSlugField
class UserProfile(models.Model):
user = models.ForeignKey(User, related_name='profile_name')
about_me = models.TextField(null=True, blank=True)
slug = AutoSlugField(populate_from='User.username', default='', unique=True)
which gives the error (when trying to migrate):
DETAIL: Key (slug)=() is duplicated.
I believe the urls to be correct but have included it for reference (in an app named profile):
url(r'^(?P<slug>[\w-]+)', views.detail, name='detail')

It means you already have some records in userprofile table with empty/null values in slug field. Because you've marked that field as unique=True it can only have one field with empty value. To avoid this error, delete the records with empty value in slug field, or just assign them a unique slug and you'll be good to go.
And as you can understand from above, having default='' in a field that has unique=True wont work. Unique means unique, even '' as an empty value is considered a unique value and can be used in just one row if you have unique=True. That also means you cannot have any default value in a unique field.

Related

Django application doesn't seem to recognize related name?

I have a django app with a User's model that contains a followers field that serves the purpose of containing who follows the user and by using related_name we can get who the User follows. Vice versa type of thing. Printing the User's followers works, but I can't seem to get the followees to work.
views.py
followers = User.objects.get(username='bellfrank2').followers.all()
following = User.objects.get(username='bellfrank2').followees.all()
print(followers)
print(following)
models.py
class User(AbstractUser):
followers = models.ManyToManyField('self', blank=True, related_name="followees")
Error:
AttributeError: 'User' object has no attribute 'followees'
According to documentation all many to many relationships that are recursive are also symmetrical by default.
See here: https://docs.djangoproject.com/en/4.0/ref/models/fields/#django.db.models.ManyToManyField.symmetrical
When Django processes this model, it identifies that it has a ManyToManyField on itself, and as a result, it doesn’t add a person_set attribute to the Person class. Instead, the ManyToManyField is assumed to be symmetrical – that is, if I am your friend, then you are my friend.
So to, make your field actually create the followees attribute you need to set the symmetrical attribute to False.
models.py
class User(AbstractUser):
followers = models.ManyToManyField('self', blank=True, related_name="followees", symmetrical=False)

Filter django query set based on whether a foreign key relationship exists

So I have two models.
class Post(models.Model):
id = models.OidField('object id', unique=True)
class ArchivedFlag(models.Model):
post = models.ForeignKey(post,
on_delete=models.CASCADE,
related_name='archived_flag')
user = models.ForeignKey(User,
on_delete=models.CASCADE,
related_name='archives')
In views.py I have generated a list of all posts by some criteria, 'plist'.
I want to filter the list based on posts that DO NOT have an ArchivedFlag object relationship. Basically the ArchivedFlag model is a tool hide certain posts.
How can I do this? I'm trying to do something along the lines of
plist = plist.exclude(models.ForeignKey.Post exists)
but I'm unsure of the exact syntax.
You can exclude Post objects for which anArchivedFlag exists with:
Post.objects.exclude(archived_flag__isnull=False)
or easier with a simple filter:
Post.objects.filter(archived_flag=None)
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

Django contrib auth users manytomany

Hello I want to make several users to one post with manytomany relationship.
from django.contrib.auth.models import User
class Post(models.Model):
author = models.ManyToManyField(User)
title = models.CharField(max_length=150)
slug = models.SlugField(max_length=255, unique=True)
body = models.TextField()
But I got this error
Post needs to have a value for field "id" before this many-to-many relationship can be used.
Can anyone tell me what the problem is?
In order to setup a many-to-many relationship the ID of the post is mandatory. Check in your database if the post(s) has an ID. The error message says its empty, so add it manually in the database (not recommended) or rerun the post its migrations and make sure the ID is auto-incremented.

Django models: database design for user and follower

In Django model I am making a table 'followers', which has:
user's id. (this is followed by)
user's id (this is follower)
that's simple a user can follow other users.
How should I define the model in Django?
I tried this, but does not work:
user = models.ForeignKey('self')
follower_id = models.ForeignKey('self')
How should this be done?
thanks
The 'self' argument won't work unless you have a model called self.
Assuming that your assignment model is called Following, and you're using the built in User model then you can do:
class Following(models.Model):
target = models.ForeignKey('User', related_name='followers')
follower = models.ForeignKey('User', related_name='targets')
This will likely need some further uniqueness and validation logic.
Note the related_name attribute, see https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.ForeignKey.related_name. This means that for a given user object you can do user.targets.all() to get users they follow, and user.followers.all() to get users who follow them.
Note also that Django returns target model instances, not IDs, in the ORM. This means that even though the underlying table may be called follower_id, in the python code following.follower will return an actual User object.
Seeing as Following is actually the through table for the many-to-many relationship between Users. I would create a Profile model which extends the Django User model, and then declare the many-to-many relationship (using ManyToManyField).
from django.contrib.auth.models import User
from django.db import models
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
following = models.ManyToManyField(User, related_name='followers')
Use the many to many field.
followers = models.ManyToManyField('self', symmetrical=False)

Django Admin Complains About A Missing Field Even When It's Not Missing

Python 2.7
Django 1.3
When I include 'user_id','user' in the admin.py, then...
no user field shows up in the form when I click to add a Timeslip.
If I submit it anyway, then it shows the user field with a "This field is required." error message.
If I pick a user & submit again, then I get "'TimeslipAdmin.fields' refers to field 'user_id' that is missing from the form." even though 'user_id' is clearly listed in my admin.py (see below)
The Traceback says --
Exception Type: ImproperlyConfigured at /admin/timeslip/timeslip/add/
Exception Value: 'TimeslipAdmin.fields' refers to field 'user_id' that is missing from the form.
But...if I leave 'user_id','user' out of the admin.py then....
no user field shows up when I click to add a Timeslip.
Submit it anyway, and it shows the user field & a "Timeslip with this User already exists." error message. (which shouldn't be an error either 'cause I want users to have multiple Timeslip's which means another error I'll have to figure out once I can just get this form working)
admin.py
from timeslip.models import Timeslip
from django.contrib import admin
class TimeslipAdmin(admin.ModelAdmin):
fields = ['user_id','user','day','hours_as_sec','part_of_day','drove','gas_money','notes']
admin.site.register(Timeslip, TimeslipAdmin)
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Timeslip(models.Model):
user=models.ForeignKey(User)
day = models.DateField()
hours_as_sec = models.PositiveIntegerField()
part_of_day = models.CharField(max_length=16,choices=PART_O_DAY)
drove = models.BooleanField(default=False)
gas_money = models.DecimalField(max_digits=5,decimal_places=2)
notes = models.TextField()
class UserProfile(models.Model):
user = models.ForeignKey(User)
url = models.URLField("Website", blank=True)
position = models.CharField(max_length=50, blank=True)
User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
I'm very clueless how to overcome this. I'm coming from a PHP background, a newbie to Python & Django.
user_id and user are redundant. Django automatically names your user field user_id in the database (since it holds the id for the User instance it points to.)
Change your admin.py to the following and it should work:
class TimeslipAdmin(admin.ModelAdmin):
fields = ['user','day','hours_as_sec','part_of_day','drove','gas_money','notes']
Also you're including all of the fields in the admin, so you really don't need to specify the fields. This would work just as well:
class TimeslipAdmin(admin.ModelAdmin):
pass
But...if I leave 'user_id','user' out of the admin.py then...
You haven't got 'user_id' field. So delete only this field and I think everything will work fine.