Get Data From A Foreign Key Django - django

I am trying to get all products related to an orderitem but am having a problem doing the query.
I want to list all products in an orderitem. Hope i have provided everything needed.
from django.core.validators import RegexValidator
from django.db import models
from django.urls import reverse
from django.utils.text import slugify
from django.contrib.auth import get_user_model
class Order(models.Model):
ref_code = models.CharField(max_length=20, blank=True, null=True)
first_name = models.CharField(('first name'), max_length=30, blank=True)
last_name = models.CharField(('last name'), max_length=30, blank=True)
class Product(models.Model):
category = models.ForeignKey(Category,related_name='products',on_delete=models.CASCADE)
name = models.CharField(max_length=200, db_index=True, unique=True)
class OrderItem(models.Model):
order = models.ForeignKey(Order,related_name='items',on_delete=models.CASCADE)
product = models.ForeignKey(Product,related_name='order_items',on_delete=models.CASCADE)
price = models.DecimalField(max_digits=10, decimal_places=2)
quantity = models.PositiveIntegerField(default=1)
slug = models.SlugField(max_length=200, db_index=True)

Try this:
# Get list of product ids of a particular order
product_ids = OrderItem.objects.filter(order=order).values_list('product', flat=True)
# Get products from list of product ids
products = Product.objects.filter(id__in=product_ids)
Let me know if it helps :)

an idea to do thas
# For all_entries
all_entries = OrderItem.objects.all() #or all_entries = OrderItem.filter(order = order)
# one orderItem
for oi in orderItem:
products_of_one_oi = oi.product
for product in products_of_one_oi:
print(product)

Related

Django rest framework not returning all fields

I am trying to make a model that stores favorite shows for users, and I have been using viewsets. I have a users and shows viewset that work just like I expect them to, and I have another model that simply stores relationships between users and shows. When I add that as a viewset though, I get the id, and user, and I don't get a show.
Here are the results for the favorites:
[
{
"id":2,
"user":{
"username":"poduck",
"first_name":"",
"last_name":"",
"email":"poduck#gmail.com",
"image":null,
"url":"http://0.0.0.0:8000/api/users/poduck/?format=json"
}
}
]
There isn't even a show field. It's not like the data isn't there either. I have been able to use queries on the data with no trouble. I have access to both the show and the user from the favorite.
I thought that maybe that the fact that the show points to a user, and the favorite points to a user that there may be some circular conflict there, but beyond excluding the user field from the Show serializer, I don't know what to do to fix that, and yes, I did try excluding it from the Show serializer.
shows.models:
from django.db import models
from django.utils.translation import gettext_lazy as _
from localflavor.us.models import USStateField, USZipCodeField
from users.models import User
from phonenumber_field.modelfields import PhoneNumberField
# Create your models here.
class Show(models.Model):
# Information
title = models.CharField(_("Title"), blank=False, max_length=255)
location = models.CharField(_("Location Name"), blank=False, max_length=255)
image = models.ImageField(upload_to='show_images', blank=True)
description = models.TextField(_("Description"), blank=False)
start_date = models.DateField(_("Start Date"), blank=False)
end_date = models.DateField(_("End Date"), blank=False)
registration_start = models.TimeField(_("Registration Start Time"), blank=False)
registration_end = models.TimeField(_("Registration End Time"), blank=False)
start_time = models.TimeField(_("Spectator Start Time"), blank=False)
end_time = models.TimeField(_("Spectator End Time"))
address = models.CharField(_("Show Address"), blank=False, max_length=255)
city = models.CharField(_("City"), blank=False, max_length=255)
state = USStateField(_("State"), blank=False, max_length=2)
zip = USZipCodeField(_("Zip Code"), blank=False)
contact_name = models.CharField(_("Contact name"), blank=True, max_length=255)
contact_email = models.EmailField(_("Contact Email"), blank=True, max_length=255)
contact_phone = PhoneNumberField(_("Contact Phone"), blank=True)
website = models.URLField(_('Official website'), blank=True)
entry_fee = models.DecimalField(_('Entry fee'), default=0.00, blank=False, decimal_places=2, max_digits=10)
spectator_entry_fee = models.DecimalField(_('Spectator entry fee'), default=0.00, blank=False, decimal_places=2, max_digits=10)
trophies = models.BooleanField(_("Trophies or Ribbons Awarded"), default=False)
dash_plaques = models.BooleanField(_("Dash Plaques Given"), default=False)
dash_plaque_quantity = models.IntegerField(_("Quantity of dash plaques to be given"), null=True, blank=True)
door_prizes = models.BooleanField(_("Door Prizes"), default=False)
judging = models.BooleanField(_("Professional Judging"), default=False)
user = models.ForeignKey(User, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
def __str__(self):
return f"{self.title}"
class Favorite(models.Model):
show = models.ForeignKey(Show, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return f"{self.show.title}"
shows.api.serializers:
from rest_framework import serializers
from shows.models import Show, Favorite
from users.api.serializers import UserSerializer
class ShowSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = Show
fields = '__all__'
class FavoriteSerializer(serializers.ModelSerializer):
show = ShowSerializer(many=True, read_only=True)
user = UserSerializer()
class Meta:
model = Favorite
fields = '__all__'
shows.api.viewsets:
from car_show_helper.shows.models import Show
from .serializers import ShowSerializer, FavoriteSerializer
from rest_framework import viewsets
class ShowViewSet(viewsets.ModelViewSet):
queryset = Show.objects.all()
serializer_class = ShowSerializer
class FavoriteViewSet(viewsets.ModelViewSet):
queryset = Show.objects.all()
serializer_class = FavoriteSerializer
And finally the api_router:
from django.conf import settings
from rest_framework.routers import DefaultRouter, SimpleRouter
from car_show_helper.users.api.views import UserViewSet
from car_show_helper.shows.api.viewsets import ShowViewSet, FavoriteViewSet
if settings.DEBUG:
router = DefaultRouter()
else:
router = SimpleRouter()
router.register("users", UserViewSet)
router.register("shows", ShowViewSet, basename="shows")
router.register("favorites", FavoriteViewSet, basename="favorites")
app_name = "api"
urlpatterns = router.urls
Any help would be appreciated.
First, change queryset inside FavoriteViewSet
class FavoriteViewSet(viewsets.ModelViewSet):
queryset = Show.objects.all()
serializer_class = FavoriteSerializer
to
queryset = Favorite.objects.all()
Second, remove many=True from:
show = ShowSerializer(read_only=True, many=True)

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.

Querying Reverse ManyToMany Relationship in Django

I have a category Model and a Product Model in my django application... the product model has a many2many field pointing to the category model... and the product model has a added field to denote when it was created.
how do i filter the categories model based on the added field value of the product?
class Category(models.Model):
#this model SHOULD BE managed by the platform admin
title = models.CharField(max_length=100)
slug = models.SlugField(blank=True)
description = models.CharField(max_length=255, blank=True, null=True)
items_count = models.PositiveIntegerField(null=True, blank=True)
updated = models.DateTimeField(auto_now=True)
image = models.ImageField(upload_to='categories_images',help_text='Generic Image describing the category very very well', null=True, blank=True)
def __str__(self):
return str(self.slug)
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super().save(*args, **kwargs)
class Product(models.Model):
title = models.CharField(max_length=50)
image = models.ImageField(upload_to='uploaded_products/', default="products/default_product.png")
description = models.TextField(max_length=255, null=True, blank=True)
categories = models.ManyToManyField(Category,related_name='products', blank=True)
tags = models.ManyToManyField(Tag, blank=True)
stock = models.PositiveIntegerField(default=1, blank=True)
added = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
uploader = models.ForeignKey(Account, on_delete=models.CASCADE, blank=True, null=True)
def __str__(self):
return self.title
i want to be able to do a query for the current trending categories based on the added field of the product.
We can first look for each Category when was the most recent Product that was added with .alias(…) [Django-doc], or with .annotate(…) [Django-doc] prior to django-3.2. We annotate this with:
from django.db.models import Max
Category.objects.alias(
most_recent_change=Max('products__added')
)
Then we can retrieve the objects through filtering. For example if we only want to retrieve Categorys updated in the last 24 hours, we can filter with:
from datetime import timedelta
from django.db.models import Max
from django.db.models.functions import Now
Category.objects.alias(
most_recent_change=Max('products__added')
).filter(
most_recent__gte=Now()-timedelta(days=1)
)
or we can make use of the timestamp provided by Django itself:
from datetime import timedelta
from django.utils.timezone import now
from django.db.models import Max
Category.objects.alias(
most_recent_change=Max('products__added')
).filter(
most_recent__gte=now()-timedelta(days=1)
)

Django permission row table to a determinate user

i'm asking a questions about permissions, i have 2 table, AnagraficaCliente and Tracking with relation 1 to many, autentichate of user is default built in with a django.contrib.auth.urls.
I searched many forum and site but i d ont understand how set permission on row for determinate users. For example:
My site is a web track to show shipped items, if i search a tracking for a user it worked, but all tracking are visible (for all users), i want that only the tracking that belongs to user show to him.
I think that i use model user from
django.contrib.auth.models import User
i don't know how work with my code.
Thanks at all.
models.py
from django.db import models
from django.urls import reverse
# Create your models here.
class AnagraficaCliente(models.Model):
codice_cliente = models.CharField(max_length=20, primary_key=True, null=False, unique=True)
ragione_sociale = models.CharField(max_length=80)
#ragione_sociale_dest = models.CharField(max_length=40)
nome = models.CharField(max_length=40, blank=True)
cognome = models.CharField(max_length=20, blank=True)
#ragione_sociale = models.CharField(max_length=20)
indirizzo = models.TextField(blank=True)
cap = models.CharField(max_length=5, blank=True)
piva = models.CharField(max_length=20, blank=True)
vatnumber = models.CharField(max_length=20, blank=True)
#ragione_sociale_dest = models.CharField(max_length=40)
#indirizzo_dest = models.TextField(null=True)
def __str__(self):
#return self.ragione_sociale + " " + self.codice_cliente
#return self.ragione_sociale_dest + " - " + self.indirizzo_dest + " - " + self.codice_cliente
return self.codice_cliente + " - " + self.ragione_sociale
class Meta:
verbose_name = "AnagraficaCliente"
verbose_name_plural = "AnagraficaClienti"
class Tracking(models.Model):
track = models.CharField(max_length=11, null=False, unique=True, primary_key=True)
indirizzo_dest = models.TextField(null=False)
passaggio1 = models.CharField(max_length=50, blank=True)
data1 = models.DateField(blank=True, null=True)
passaggio2 = models.CharField(max_length=50, blank=True)
data2 = models.DateField(blank=True, null=True)
passaggio3 = models.CharField(max_length=50, blank=True)
data3 = models.DateField(blank=True, null=True)
passaggio4 = models.CharField(max_length=50, blank=True)
data4 = models.DateField(blank=True, null=True)
passaggio5 = models.CharField(max_length=50, blank=True)
data5 = models.DateField(blank=True, null=True)
consegna = (
('C', 'Consegnato'),
('N', 'Non consegnato'),
)
consegnato = models.CharField(
max_length=1, choices=consegna, blank=True, null=True)
#consegnato = models.BooleanField(blank=True)
#esito = models.CharField(max_length=10, blank=True)
flag = models.CharField(max_length=2, blank=True)
AnagraficaCliente = models.ForeignKey(AnagraficaCliente, on_delete=models.CASCADE, related_name='trackings')
def __str__(self):
return self.track
class Meta:
verbose_name = "Tracking"
verbose_name_plural = "Trackings"
admin.py
from django.contrib import admin
from .models import AnagraficaCliente, Tracking
from import_export.admin import ImportExportModelAdmin
#from import_export.admin import ImportExportActionModelAdmin
from import_export import resources
# Register your models here.
class ClientResource(resources.ModelResource):
class Meta:
model = AnagraficaCliente
skip_unchanged = True
report_skipped = True
#fields = ('id','codice_cliente','ragione_sociale','nome','cognome','ragione_sociale','indirizzo','cap','piva','vatnumber')
import_id_fields = ['codice_cliente']
#admin.register(AnagraficaCliente)#Decoratore per mostrare in admin anagraficacliente
class SearchCodice(admin.ModelAdmin):
search_fields = ('codice_cliente', 'ragione_sociale')#Ricerca in admin
list_display = ('codice_cliente','ragione_sociale','indirizzo')#Elenco nomi campo nelle tabelle
class ClientAdmin(ImportExportModelAdmin):
resource_class = ClientResource #Classe per import export csv punta alla classe ClientResource
class ClientResource(resources.ModelResource):
class Meta:
model = Tracking
skip_unchanged = True
report_skipped = True
#fields = ('id','codice_cliente','ragione_sociale','nome','cognome','ragione_sociale','indirizzo','cap','piva','vatnumber')
import_id_fields = ['track']
#admin.register(Tracking)
class SearchTrack(admin.ModelAdmin):
search_fields = ('track', 'consegnato')
list_display = ('track','indirizzo_dest','consegnato')
Ok, i solved in this way:
in models i have add a new field that will contain the exact name of user (see the comment):
user = models.CharField(max_length=20, blank=True)
in views in query objects i change this line:
def tracking_views(request):
query = request.GET.get('q', None)
context = {}
#query_anag = AnagraficaCliente.objects.all()
if query and request.method == 'GET':
#results = Tracking.objects.filter(track=query)#Old line, see next line
results = Tracking.objects.filter(track=query, user=request.user) #Line that
changed
print (type(results))
if results.exists():
context.update({'results': results})
print(context)
else:
return render(request,'tracking_not_found.html',context)
# return HttpResponse("<h1>post creato con successo!</h1>")
return render(request,'tracking.html',context)
So when user is authenticated only the query with number of tracking that belongs to a user will be showed, (of course in every record need to mapped the row of tacking to a new field "user")

How to assign subject name to their proper field

I have used django-import-export package. And want to have related database from csv file of format,
roll_no,student_name,subject_1_mark,subject_2_mark,....subject_n_mark
i'm having difficulty of assigning subject mark to their appropriate field on django ORM
example:
#csv file
roll_no, student_name, FOCP, IT, OS, DS, DL
201,john,56,34,65,34,68
Models.py
class Student(models.Model):
""" Store Student Information """
student_name = models.CharField(max_length=255)
roll_no = models.IntegerField()
class Subject(models.Model):
""" Store Subject Information """
subject_name = models.CharField(max_length=150, null=True, blank=True)
sub_code = models.CharField(max_length=255, unique=True, null=True,blank=True)
class Exam(models.Model):
""" Store Exam Information """
exam_type = models.CharField(max_length=150, null=True, blank=True)
exam_date = models.DateField(null=True, blank=True)
class Mark(models.Model):
""" Store Mark Information """
subject_name = models.ForeignKey(Subject, related_name='marks', null=True, blank=True)
exam = models.ForeignKey(Exam, related_name='marks', null=True, blank=True)
mark = models.IntegerField(null=True, blank=True)
settings.py
INSTALLED_APPS = (
...
'import_export',
)
admin.py
from django.contrib import admin
from import_export.admin import ImportExportModelAdmin
from import_export import resources
from .models import Subject
class SubjectResource(resources.ModelResource):
class Meta:
model = Subject
class SubjectAdmin(ImportExportModelAdmin, admin.ModelAdmin):
resource_class = SubjectResource
admin.site.register(Subject, SubjectAdmin)
Use Fields for mapping
Field represent mapping between object field and representation of this field.
I override before_import and did some additional logic on data that solve my problem. I had opened issue on github https://github.com/django-import-export/django-import-export/issues/644#issuecomment-320966810