django 3.0 inline admin form foreignkey -> foreignkey - django

I have any models and one Manager
app/models.py
class castratedListStudent(models.Manager):
use_in_migrations = False
def get_query_set(self):
return super().get_query_set().filter(isOn=1)
class student(models.Model):
id = models.AutoField(primary_key=True)
firstName = models.CharField(max_length=20)
lastName = models.CharField(max_length=20)
isOn = models.BooleanField()
default_manager = castratedListStudent()
objects = castratedListStudent()
class discipline(models.Model):
id = models.AutoField(primary_key=True)
nameDiscipline = models.CharField(max_length=100, null=False)
itemIdToDiscip = models.ForeignKey(item, on_delete=models.CASCADE, default=1)
class listOfStudForDiscipline(models.Model):
id = models.AutoField(primary_key=True)
discipListId = models.ForeignKey(discipline, on_delete=models.CASCADE)
studId = models.ForeignKey(student, on_delete=models.CASCADE)
I am using django inline
accounts/admin.py
class discipStudentInline(admin.TabularInline):
model = listOfStudForDiscipline
admin.TabularInline.verbose_name = 'Student'
extra = 0
def has_change_permission(self, request, obj=None):
return False
def get_queryset(self, request):
return self.model.objects.filter(studId__isOn=1)
class disciplineAdmin(admin.ModelAdmin):
model = discipline
inlines = [discipStudentInline]
The Inline form is displayed on the HTML page and filter (studId__isOn=1) works. But the problem is that on the HTML page below there is a field that allows you to add another student and the list of students is not filtered by the filter rule(studId__isOn=1) When I check in the DEBUG_SQL console, I can see how the query goes without the WHERE expression "FROM journal_student".
(0.000) SELECT `journal_listofstudfordiscipline`.`id`, `journal_listofstudfordiscipline`.`discipListId_id`, `journal_listofstudfordiscipline`.`studId_id` FROM `journal_listofstudfordiscipline` INNER JOIN `journal_student` ON (`journal_listofstudfordiscipline`.`studId_id` = `journal_student`.`id`) WHERE (`journal_student`.`isOn` = 1 AND journal_listofstudfordiscipline`.`discipListId_id` = 1) ORDER BY `journal_student`.`lastName` DESC; args=(True, 1)
(0.000) SELECT `journal_student`.`id`,..., `journal_student`.`descriptionStudent` FROM journal_student` ORDER BY `journal_student`.`lastName` ASC, `journal_student`.`firstName` ASC; args=()
I couldn't solve the problem using the model Manager.

I solved the problem. It turned out that after django version 1.7, the get_query_set() method was renamed to get_queryset(). And the Manager will now look like this:
class castratedListStudent(models.Manager):
use_in_migrations = False
def get_query_set(self):
return super(liveListStudent, self).get_queryset().filter(isOn=1)

Related

How to retrieve data from model that current user created and list it for another model's field in django

Let us imagine that I have two models.
First model contains curse details and user that created this course
class Course(models.Model):
course_name = models.CharField(max_length=100, null=False)
description = models.CharField(max_length=255)
user_profile = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
and my second model is:
class Lesson(models.Model):
course = models.OneToOneField(Course, on_delete=models.CASCADE) #
# inside the course I want my APIVIEW to list only the courses that current user created.
# OnetoOne relationship does not solve the problem.
status = models.CharField(choices=STATUS, null=False, default=GOZLEMEDE,max_length=20)
tariffs = models.FloatField(max_length=5,null=False,default=0.00)
continues_off = models.CharField(max_length=2)
user_profile = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
My serializers for both Models:
class LessonSerializer(serializers.ModelSerializer):
class Meta:
model = models.Lesson
fields = ('course', 'status', 'tariffs', 'continues_off', 'user_profile')
def create(self, validated_data):
lesson = models.Lesson.objects.create(
course = validated_data['course'],
status = validated_data['status'],
tariffs=validated_data['tariffs'],
continues_off=validated_data['continues_off'],
user_profile=validated_data['user_profile']
)
return lesson
class CourseSerializer(serializers.ModelSerializer):
"""Serializers Course content"""
class Meta:
model = models.Course
fields = '__all__'
def create(self,validated_data):
course = models.Course.objects.create(
course_name = validated_data['course_name'],
description=validated_data['description'],
user_profile=validated_data['user_profile']
)
return course
My Viewset:
class LessonViewset(viewsets.ModelViewSet):
model = models.Lesson
serializer_class = serializers.LessonSerializer
authentication_classes = (SessionAuthentication,)
permission_classes = (IsAuthenticated,BasePermission,)
def get_queryset(self):
user_current = self.request.user.id
return models.Lesson.objects.filter(user_profile=user_current)
How can I get the desired result. I want to get the courses for the current user and show them as a dropdown list in my API view. Just only the courses that user created should be in the dropdown list not all.
OnetoOne relationship gives all results of course table.
i think change your view code to :
def get_queryset(self,id):
return model.objects.filter(user_profile=id)
#You do not need to call it again when you put the Lesson on the model
\

Insert data into intermediary table while submitting main modelform in Django

I have a Task model. I want to assign task to multiple users so i have taken ManytoMany relationship. So Django is creating a ManytoMany table but i want to track that which user has completed task and when. So I took intermediary model by using through='TaskComplete'. Now I can not see task_assign_to feild in form. And even i declare in modelForms and submit it gives below error.
Cannot set values on a `ManyToManyField` which specifies an intermediary model. Use audit.TaskComplete's Manager instead.
Now I want that admin selects the user from main form and into intermediary model.
I tried but can not find any solution for this. below is my code. Please guide me how to do it?
My Model:
class Task(models.Model):
task_audit_title = models.ForeignKey(MainAudit,on_delete= models.CASCADE, related_name='audit_title_for_task',verbose_name= ('Audit Title'))
task_subtask_name = models.ManyToManyField(SubTask, related_name='subtask_for_task',verbose_name= ('Subtask Title'))
task_subject = models.CharField(verbose_name= ('Task Subject'),max_length=100,blank=False)
task_description = models.CharField(verbose_name= ('Task Description'),max_length=1000,blank=True)
task_assign_to = models.ManyToManyField(User, related_name='task_assign_to', through='TaskComplete')
task_assign_by = models.ForeignKey(User,on_delete= models.CASCADE, related_name='task_crt_by')
task_deadline = models.DateTimeField(null=True,blank=True)
task_perticulars = models.ManyToManyField(Perticular, related_name='task_perticular', blank=True)
task_created_time = models.DateTimeField(default=timezone.now)
task_modified_by = models.ForeignKey(User,on_delete= models.CASCADE, related_name='task_mod_by', null=True, blank=True)
task_modified_time = models.DateTimeField(null=True,blank=True)
is_del = models.BooleanField(default=0)
class Meta:
permissions = (
("change_temp_delete_task", "Can delete temporarily"),
)
def __str__(self):
return self.task_subject
def get_absolute_url(self):
return reverse('create-task')
class TaskComplete(models.Model):
task_title = models.ForeignKey(Task,on_delete= models.CASCADE, related_name='assigned_task')
is_completed = models.BooleanField(default=0)
task_cmt_by_doer = models.CharField(verbose_name= ('Submit Comment'),max_length=100,blank=True)
completed_by = models.ForeignKey(User,on_delete= models.CASCADE, related_name = 'task_completed_by')
completed_time = models.DateTimeField(null=True,blank=True)
My View:-
class TaskCraeteView(LoginRequiredMixin,SuccessMessageMixin,CreateView):
# permission_required = 'Company.add_company'
model=Task
success_message = " Task Craeted successfully!"
reverse_lazy('create-task')
login_url = 'login'
template_name = 'create-task'
form_class = TaskCreateForm
# fields =[]
def form_valid(self,form):
form.instance.task_assign_by = self.request.user
My traceback my traceback link
My Form
class TaskCreateForm(forms.ModelForm):
class Meta:
model = Task
fields = ['task_audit_title','task_subtask_name','task_subject','task_description',
'task_assign_to','task_deadline','task_perticulars']

Django FOREIGN KEY constraint failed

My app is a shopping cart. I have a function in views.py that is triggered when someone adds an item to the cart. The function checks if the user has an active order (one that is in the cart but hasn't been paid for).
But the code fails at `user_order, status = Order.objects.get_or_create(owner=user_profile, is_ordered=False)
#login_required()
def add_to_cart(request, **kwargs):
#get the user profile
user_profile = get_object_or_404(UserProfile, user=request.user)
#filter products by id
producto = Producto.objects.filter(id=kwargs.get("pk", "")).first()
#create OrderItem, of the selected product
order_item, status = OrderItem.objects.get_or_create(producto=producto)
if status == False: #adds one to the order_item
order_item.quantity += 1
order_item.save()
print(order_item.quantity)
#create order associated with the user
user_order, status = Order.objects.get_or_create(owner=user_profile, is_ordered=False)
user_order.items.add(order_item)
#print(user_order.items.all()) #queries the items
#print(user_order)
#date is not beign added
# generate a reference code
user_order.ref_code =random.randint(0,100000)
user_order.save()
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
Relevant models:
class Order(models.Model):
fecha_reparto = models.OneToOneField(DiasDeReparto, on_delete=models.CASCADE, default= 1)
order_nodo = models.OneToOneField(Nodo, on_delete=models.CASCADE, default= 1)
ref_code = models.CharField(max_length=15)
owner = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
is_ordered = models.BooleanField(default=False)
items = models.ManyToManyField(OrderItem)
date_ordered = models.DateTimeField(null=True)
def get_cart_items(self):
return self.items.all()
def get_cart_total(self):
return sum([item.producto.precio * item.quantity for item in self.items.all()])
def __str__(self):
return self.ref_code
class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
class OrderItem(models.Model):
producto = models.OneToOneField(Producto, on_delete=models.SET_NULL, null = True)
quantity = models.IntegerField(default=1)
is_ordered = models.BooleanField(default=False)
date_added = models.DateTimeField(auto_now = True)
date_ordered = models.DateTimeField(null=True)
def __str__(self):
return self.producto.nombre
The problem can be solved with something like this:
try:
Order.objects.get(owner=user_profile)
except:
Order.objects.create(fecha_reparto=dia_reparto[0], order_nodo=nodo[0], ref_code="asdas", owner=user_profile, is_ordered=False, date_ordered=datetime.datetime.now())
But I don't get why get_or_create doesn't work
On your Order model you have a few related model fields and in the get_or_create you are not specifying any defaults. The get or create needs the required values to input if creating and you have a few related fields which are required. That will also explain why the try and except works because you add the fields when creating in the except.
defaults = {fecha_reparto: dia_reparto[0], order_nodo: nodo[0]......}
user_order, status = Order.objects.get_or_create(owner=user_profile, is_ordered=False, defaults=defaults)
Use id instead model instace in this line:
user_order, status = Order.objects.get_or_create(owner=user_profile, is_ordered=False)
So it should look like this:
user_order, status = Order.objects.get_or_create(owner_id=user_profile.pk, is_ordered=False)
It worked for me with similar problem.

How to send info in URL?

I am trying to create a product filter.
I am sending the user choice in URL
if the user select size = L then using request.GET
I am receiving:
{'size': ['L']}
But I want to receive: {'size':{'op':'in','attri':'L'}}
Is this possible?
Please help
my models are
class ProductAttribute(models.Model):
slug = models.SlugField(max_length=50, unique=True)
name = models.CharField(max_length=100)
op = models.CharField(max_length=20,default='in')
class Meta:
ordering = ('slug', )
def __str__(self):
return self.name
def get_formfield_name(self):
return slugify('attribute-%s' % self.slug, allow_unicode=True)
def has_values(self):
return self.values.exists()
class AttributeChoiceValue(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(max_length=100)
attribute = models.ForeignKey(
ProductAttribute, related_name='values', on_delete=models.CASCADE)
class Meta:
unique_together = ('name', 'attribute')
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=128)
attributes = HStoreField(default={})
q2 = AttributeChoiceValue.objects.filter(attribute__name='size')
My size filter(filter.py) is:
size = django_filters.ModelMultipleChoiceFilter(queryset=q2.values_list('name', flat=True).distinct(),widget=forms.CheckboxSelectMultiple)
I am currently using the following query to filter my database in views.py
result = Product.objects.all()
for key, value in request.GET:result = result.filter(**{'attributes__{}__in'.format(key): value})
I want to make it
a=request.GET
for key, value in a:
result = result.filter(**{'attributes__{}__{}'.format(key,a['op']): value})
so that if I even use Price range as filter my query filter accordingly will be
attributes__price__range
You can send info to your views via "path converters":
https://docs.djangoproject.com/en/2.0/topics/http/urls/#path-converters
Or using regular expressions:
https://docs.djangoproject.com/en/2.0/topics/http/urls/#using-regular-expressions

How to use djando-table2 with class based view to display data from multiple table?

models.py
class DailyRecordManager(models.Manager):
def get_query_set(self):
qs = super(DailyRecordManager, self).get_query_set().order_by('date_organised')
return qs
class DailyRecord(models.Model):
date_organised = models.DateField('Ogransied Date', help_text=('Enter Date when the program is organised: CCYY-MM-DD'))
program_name = models.TextField('program name',)
venue = models.CharField('venue', max_length = 255, blank=True)
organiser = models.ForeignKey(Organiser, verbose_name = 'Organiser', related_name = 'organisers')
objects = models.Manager()
public = DailyRecordManager()
class Meta:
verbose_name = 'dailyrecord'
verbose_name_plural = 'dailyrecords'
ordering = ['-date_organised']
def __str__(self):
return self.program_name
class Participant(models.Model):
participant = models.CharField(max_length= 50, unique = True)
daily_record = models.ForeignKey(DailyRecord, verbose_name = 'program_name')
class Meta:
verbose_name = 'participant'
verbose_name_plural = 'participants'
def __str__(self):
return self.participant
views.py
class DailyActivityPageView(SingleTableView):
table_class = DailyRecordTable
queryset = DailyRecord.public.all()
# queryset = Participant(DailyRecord.public.all()) is not working
template_name = 'dailyrecord/daily-activity-record.html'
tables.py
class DailyRecordTable(tables.Table):
date_organised = tables.Column('Date')
program_name = tables.Column( 'Program Name')
venue = tables.Column( 'Venue')
organiser = tables.Column( 'Organiser')
participant = tables.Column( 'dailyrecord.participant')
# daily = tables.RelatedLinkColumn()
class Meta:
model = DailyRecord
Now what I need is to display the data from participant table too, corresponding to the daily_record foreign key.
Click this link to view the snapshot. see the last column of the table. I need the data of Participant.partcipant column here
Sorry for poor English.
Thank You
There are two problems here.
First is, that a daily record can have multiple participants. Thus, in order to fill last column you have to aggregate all possible participants into that column (for example as list).
Second is, that you should make Participant backwards related to DailyRecord by adding attribute "related_name" to daily_record in your Participant model, like this:
daily_record = models.ForeignKey(DailyRecord, verbose_name = 'program_name', related_name="participants")
Now, you should simply get participants from daily_record like this:
participants = DailyRecord.public.first().participants.all()
If you had OneToOneField instead of ForeignKey you could add (single) participant to table like this:
participant = tables.Column( "Participant", accessor='participant')