django retrieving all objects from one to many model relationship in shell - django

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

Related

Recording user activity in django?

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.

Django Signals: Can't Use For Loop?

When i remove the for loop in the signals then it works (creates an object properly) but when i use the for loop it should create an object for each post in the Collection object but this doesn't work. It doesn't even create an object of the Collection_List_Item model. Is there a reason why this for loop doesn't work? Is there a way to work around this?
models
class Collection(models.Model):
posts = models.ManyToManyField(Post, related_name='collection_posts', blank=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
collection_name = models.CharField(max_length=100)
collection_description = models.CharField(max_length=1000, blank=True)
collection_likes = models.ManyToManyField(User, related_name='liked_collections', blank=True)
collection_image = models.ImageField(upload_to="images/")
private = models.BooleanField(default=False)
follows = models.ManyToManyField(User, related_name='collection_follows', blank=True)
def __str__(self):
return self.collection_name
class Collection_List_Item(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, null=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
collection = models.ForeignKey(Collection, on_delete=models.CASCADE, null=True)
saved = models.BooleanField(default=False)
created_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
def __str__(self):
return self.collection.collection_name
signals:
#receiver(post_save, sender=Collection)
def create_collection_list_item(sender, instance, created, **kwargs):
if created:
for i in instance.posts.all():
collection_list_item = Collection_List_Item.objects.create(collection=instance, user=instance.author, post=i)
collection_list_item.save()
For ManyToManyField fields you have to use m2m_changed (Django Docs) signal.
Because ManyToManyField are saved after instance is saved and thus there won't be any record at all of the ManyToManyField updates.
from django.db.models.signals import m2m_changed
from django.db import IntegrityError
#receiver(m2m_changed, sender=Collection.posts.through)
def create_collection_list_item(sender, instance, action, *args, **kwargs):
if action == "post_add":
for i in instance.posts.all():
try:
collection_list_item = Collection_List_Item.objects.create(collection=instance, user=instance.author, post=i)
except IntegrityError:
pass

Is it possible in Django to call custom `QuerySet` method on reverse related objects lookup?

E.g. there are next models and custom QuerySet:
from django.db import models
class ActiveQuerySet(models.QuerySet):
def active(self):
'''returns only active objects'''
'''supposing here would be a lot
of more complicated code
that would be great to reuse
'''
return self.filter(is_active=True)
class Category(models.Model):
name = models.CharField(max_length=128, blank=True, null=True, default=None)
class Product(models.Model):
name = models.CharField(max_length=128, blank=True, null=True)
is_active = models.BooleanField(default=True)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, related_name='products', related_query_name="product", blank=True, null=True, default=None)
objects = ActiveQuerySet.as_manager()
Could you tell me if there is a way to call the active() method like this:
category = Category.objects.first()
category.products.active()
instead of doing like this:
category.products.filter(is_active=True)
Or how to implement appropriately such behavior?
You have to add the custom queryset into the parent model, not the _set. You can change custom_products to any other word.
class ActiveQuerySet(models.QuerySet):
def active(self):
'''returns only active objects'''
'''supposing here would be a lot
of more complicated code
that would be great to reuse
'''
return self.products.filter(is_active=True)
class Category(models.Model):
name = models.CharField(max_length=128, blank=True, null=True, default=None)
custom_products = ActiveQuerySet.as_manager()
category.custom_products.active()

Add Depandent drop down list for Django admin user

I have created 4 models in my django Country, State, and City, and also add them in admin.site.register How Can I add dependent drop down list for Country State City for admin user whenever user try to create Aplications object, they get state name list depends on Country name selected by admin user, and also for city.
Models.py
from django.db import models
from django.db.models import ForeignKey
from multiselectfield import MultiSelectField
class Country(models.Model):
name = models.CharField(max_length=250)
phone_code = models.CharField(max_length=250)
currency = models.CharField(max_length=250)
def __str__(self):
return self.name
class State(models.Model):
name = models.CharField(max_length=250)
country = models.ForeignKey(to=Country, on_delete=models.CASCADE)
def __str__(self):
return self.name
class City(models.Model):
state = models.ForeignKey(to=State, on_delete=models.CASCADE)
name = models.CharField(max_length=250)
def __str__(self):
return self.name
class Applications(models.Model):
country = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True)
state = models.ForeignKey(State, on_delete=models.SET_NULL, null=True)
city = models.ForeignKey(City, on_delete=models.SET_NULL, null=True)
name = models.CharField(max_length=20)
phone_number = models.IntegerField()
email_id = models.EmailField()
home_address = models.CharField(max_length=255, blank=True, null=True)
birthdate = models.DateField(null=True, blank=True)
current_company = models.TextField(max_length=250, blank=True, null=True)
def __str__(self):
return str(self.name)
they get state name list depends on Country name selected by admin user, and also for city
Since you said a dropdown list, I will suggest switching over to a multiple choice field where the choices will be set to a certain range of values and will appear as a dropdown in the admin dashboard.

Django models not allowing one to many relationship

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