Having a really tough time wrapping my head around creating this model set for Django. Currently I am creating a site where a user can click the article to decide that he or she likes the article. I have set up the models to include article, favorite articles, and user. However, currently the way I have it set up is for it to only allow the user to have one favorite article, not two. I am using the ForeignKey field and that is not working. Here they are
from django.db import models
# users/models.py
from django.contrib.auth.models import AbstractUser
from django.db.models.signals import post_save
from django.dispatch import receiver
import uuid
class Article(models.Model):
title = models.CharField(max_length=120, primary_key=True)
content = models.TextField()
url=models.CharField(max_length=200, null=True)
category = models.CharField(max_length=250, null =True)
def __str__(self):
return self.title
class CustomUser(AbstractUser):
username = models.CharField(max_length=50, unique=True, primary_key=True)
git = models.CharField(max_length=200, null=True)
homepage = models.CharField(max_length=250, null=True)
def __str__(self):
return str(self.username)
class FavoriteArticles(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='user', null=True)
fav_title = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='fav_title', null=True)
reasons = models.CharField(max_length=120, null=True)
favcategory = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='favcategory', max_length=250, null =True)
# def __str__(self):
# return self.user
Related
How can I declare the previous or next attributes pointing to the same class type ?
I couln't find the answer in official documentation
In the models.py below I have just written "scenes" for previous and next
from pickle import TRUE
from django.db import models
from django.contrib.auth.models import User
class scenes(models.Model):
name = models.CharField('Event name', max_length=120)
record_date = models.DateTimeField('Event date')
manager = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)
description = models.TextField(blank=True)
previous = models.ForeignKey(scenes, blank=True, null=True, on_delete=models.SET_NULL)
next = models.ForeignKey(scenes, blank=True, null=True, on_delete=models.SET_NULL)
def __str__(self):
return self.name
You can use 'self' to refer to the same model. But here you likely can work with a OneToOneField [Django-doc] with next as value for the related_name=… parameter [Django-doc] for the previous field. That way when you set B as the next of A, A is the previous of B automatically:
from pickle import TRUE
from django.db import models
from django.conf import settings
class scenes(models.Model):
name = models.CharField('Event name', max_length=120)
record_date = models.DateTimeField('Event date')
manager = models.ForeignKey(
settings.AUTH_USER_MODEL,
blank=True,
null=True,
on_delete=models.SET_NULL
)
description = models.TextField(blank=True)
previous = models.OneToOneField(
'self',
blank=True,
null=True,
related_name='next'
on_delete=models.SET_NULL
)
def __str__(self):
return self.name
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.
I am creating an API. When i create a new user, or edit an existing user and save, i get this error
"AttributeError at /admin/accounts/user/1/change/
'User' object has no attribute 'profile"
For clarity, I have a user model and a profile model lied o my User model with a onetoone relationship.
Here is my User model
artist_name = models.CharField(
max_length=255,
default='artist name',
unique=True
)
slug = models.SlugField(max_length=250, null=True, blank=True)
email = models.EmailField(max_length=300, unique=True)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False)
admin = models.BooleanField(default=False)
date_joined = models.DateTimeField(auto_now_add=True)
last_login = models.DateTimeField(auto_now_add=True)
My Profile model
class Profile(models.Model):
user = models.OneToOneField(
User,
on_delete=models.CASCADE,
related_name="user",
default=1
)
first_name = models.CharField(max_length=255, blank=True, null=True)
last_name = models.CharField(max_length=255, blank=True, null=True)
country = models.CharField(max_length=500, blank=True, null=True)
gender = models.CharField(max_length = 20, blank=True, null=True)
record_label = models.CharField(max_length=255, blank=True, null=True)
image = models.FileField()
And my signals
from .models import User, Profile
from django.dispatch import receiver
#receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()
I should also mention that I don't have views for my user and profile yet. But i don't think that should affect the admin area.
So far i have searched online but nothing worked.
Thank you in anticipation.
i would advice you not to create a seperate user model, rather use the default User model. note that some of the features you need on your Profile model are actually present in the User model. in User model you have first_name, last_name,email,username, password1 and password2 by default but if you only what to use the User model you specified then follow the steps. so in your profile model the fields you should specify should be as follows:
from django.contrib.auth.models import User
from .models import User, Profile
from django.dispatch import receiver
from django.db.models.signals import post_save
class User(models.Model):
artist_name = models.CharField(max_length=255, default='artist name', unique=True)
slug = models.SlugField(max_length=250, null=True, blank=True)
email = models.EmailField(max_length=300, unique=True)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False)
admin = models.BooleanField(default=False)
date_joined = models.DateTimeField(auto_now_add=True)
last_login = models.DateTimeField(auto_now_add=True)
class Profile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
country = models.CharField(max_length=500, blank=True, null=True)
gender = models.CharField(max_length = 20, blank=True, null=True)
record_label = models.CharField(max_length=255, blank=True, null=True)
image = models.ImageField()
#receiver(post_save, sender=User)
def create_profile(sender, instance, created, *args, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_profile(sender, created, instance, **kwargs):
if not created:
instance.profile.save()
I hope this helps and if it does vote up this answer and give response.
I have a project in which some user can perform CRUD activities. I want to record who did what and when. Currently, I am thinking of making a model
class UserAction(models.Model):
user_id = models.CharField(max_length=100)
action_flag = models.CharField(max_length=100)
class_id = models.CharField(max_length=100)
action_taken_at = models.DateTimeField(default=datetime.now())
and making a function that fills my UserAction table. Is there any better way to do this?
app/models.py:
from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
class Action(models.Model):
sender = models.ForeignKey(User,related_name='user',on_delete=models.CASCADE)
verb = models.CharField(max_length=255)
target_ct = models.ForeignKey(ContentType, blank=True, null=True,
related_name='target_obj', on_delete=models.CASCADE)
target_id = models.PositiveIntegerField(null=True, blank=True)
target = GenericForeignKey('target_ct', 'target_id')
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-created',)
def __str__(self):
return self.pk
app/admin.py
from .models import Action
admin.site.register(Action)
How you can use it ?
you can now import this models(Action) inside any of yours views.py.
Example if you have a post and a user likes it.you can just write
Action.objects.create(sender=request.user,verb="likes this post",target=post)
and now when you look at your admin you will see that tartget_id=post.pk
Here I assume that a user is authenticated and you can change it for your own.Happy coding!!!
You can do it by creating a model in
Models.py
class Auditable(models.Model):
ip = models.GenericIPAddressField(null=True)
user_agent = models.CharField(max_length=255, blank=True)
remote_host = models.CharField(max_length=255, blank=True)
created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, related_name="%(app_label)s_%(class)s_created_by", null=True, blank=True) # this is for web user
modified_at = models.DateTimeField(auto_now=True, blank=True, null=True)
modified_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, related_name="%(app_label)s_%(class)s_modified_by", null=True, blank=True) # this is for web user
class Meta:
abstract = True
def get_fields(self):
list_fields = ['ip', 'user_agent',
'remote_host', 'created_by', 'modified_by']
return [(field.verbose_name, field._get_val_from_obj(self)) for field in self.__class__._meta.fields if field.name not in list_fields and not
(field.get_internal_type() == "DateTimeField" and
(field.auto_now is True or field.auto_now_add is True)) and
field.concrete and (not field.is_relation or field.one_to_one or
(field.many_to_one and field.related_model))]
You can give any class name (i have given auditable). So all you have to do is pass this class (auditable) in your every model instead of models.Model
For Eg:
class Student(Auditable):
By doing this it will add all the auditable fields records in every table you have created.
Hope you may get your answer by doing this.
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Board(models.Model):
title = models.CharField(max_length=50, null=True)
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.title
class Task(models.Model):
title = models.CharField(max_length=200, null=True)
done = models.BooleanField(default=False, null=True)
created_at = models.DateTimeField(auto_now_add=True, null=True)
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
board = models.ForeignKey(Board, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.title
how can I get all tasks that are inside one board? (every user can create a board and inside that board the user can create tasks) I've tried Board.objects.get(pk=1).title.title but that doesn't seem to work.
You can retrieve the Board object, and then query with task_set:
board = Board.objects.get(pk=1)
board.task_set.all() # queryset of related Tasks
If you are not interested in the Board itself, you can omit querying the Board, and filter with:
Task.objects.filter(board_id=1) # queryset of related Tasks
Currently I have a site, and I want the user to be able to view their liked articles. I want this to be included in the user api view that is already set up. I have tried the tracks = serializers.StringRelatedField(many=True)that is in the drf docs yet this didn't work. I have also tried the following:
from rest_framework import serializers
from articles.models import Article, CustomUser,FavoriteArticles
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ('title', 'content')
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = CustomUser
fields = '__all__'
class FavoriteArticleSerializer(serializers.ModelSerializer):
class Meta:
model = FavoriteArticles
fields = '__all__'
class UserProfileSerializer(serializers.ModelSerializer):
fav_title = FavoriteArticleSerializer(read_only=False)
class Meta:
model = CustomUser
fields = 'username, git, email, fav_article, fav_title, homepage'
and my models:
from django.db import models
# users/models.py
from django.contrib.auth.models import AbstractUser
from django.db.models.signals import post_save
from django.dispatch import receiver
import uuid
class ProgrammingLanguage(models.Model):
programming_language = models.CharField(max_length=120, null=False, primary_key=True, default="React")
def __str__(self):
return self.programming_language
class Article(models.Model):
title = models.CharField(max_length=25, primary_key=True)
content = models.TextField()
usedfor = models.TextField()
url=models.CharField(max_length=200, null=True)
article_programming_language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE, related_name="article_programming_language", default="react")
score = models.IntegerField(max_length=5, null=0)
def __str__(self):
return self.title
class CustomUser(AbstractUser):
username = models.CharField(max_length=50, unique=True, primary_key=True)
git = models.CharField(max_length=200, null=True)
homepage = models.CharField(max_length=250, null=True)
user_programming_language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE, related_name="most_used_programming_language", default="react")
def __str__(self):
return str(self.username)
class FavoriteArticles(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
fav_title = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='fav_title')
reasons_liked = models.CharField(max_length=120, null=True)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name="user", default="tom" )
def __unicode__(self):
return '%s: %s' % (self.fav_title, self.reasons_liked)
I think you misunderstood what related_name means. It specifies how you would access a model from its reverse relationship. So I'd recommend you remove it from fields in your FavoriteArticles model and use the default Django already provides (in this case favoritearticles_set):
class FavoriteArticles(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
fav_title = models.ForeignKey(Article, on_delete=models.CASCADE)
reasons_liked = models.CharField(max_length=120, null=True)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, default="tom")
def __unicode__(self):
return '%s: %s' % (self.fav_title, self.reasons_liked)
This way, you can access favorite articles of a user via my_user.favoritearticles_set.all(). Then, you can change your UserSerializer to include a liked_articles field which is populated from the favoritearticles_set reverse relationship to a user's FavoriteArticles using a source attribute:
class UserSerializer(serializers.ModelSerializer):
liked_articles = FavoriteArticleSerializer(source='favoritearticles_set', many=True, read_only=True)
class Meta:
model = CustomUser
# explicitly include other fields as required
fields = ('username', 'git', 'user_programming_language', 'liked_articles')
Note that we've made this a read_only field, so it will only get populated if you perform a GET request.