Three-way query in django - django

I have the following model:
class Video(models.Model):
name = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
filename = models.CharField(max_length=200)
duration = models.IntegerField(default=0)
votes_up = models.IntegerField(default=0)
votes_down = models.IntegerField(default=0)
width = models.IntegerField(default=0)
height = models.IntegerField(default=0)
def __unicode__(self):
return self.name
class Category(models.Model):
name = models.CharField(max_length=200)
def __unicode__(self):
return self.name
class VideoCategory(models.Model):
video = models.ForeignKey('Video')
category = models.ForeignKey('Category')
def __unicode__(self):
return u"{} >> {}".format(self.video.name, self.category.name)
And this view:
def video_list(request):
if 'category' in request.POST:
#####
else:
video_list = Video.objects.order_by('pub_date')
context = {}
context['videos'] = []
for video in video_list:
video_data = {'name': video.name,
'file': video.filename,
'duration': video.duration,
'resolution': [video.width, video.height],
}
context['videos'].append(video_data)
return HttpResponse(json.dumps(context), content_type="application/json")
Everything works as expected.
Now I want to filter videos through categories. How can I construct a query like:
"Give me all the 'Videos', which have an entry in 'VideoCategory' with the 'Category'.name like 'xxxxxxx'"

You can do:
videos = Video.objects.filter(videocategory__category__name='xxxx')
(notice the lower case model name to access the reverse relationship)
You can read upon how to query lookups that span relationships here

Related

how to return several FileField from Queryset in Django?

I have a models with FileField for videos.
When i upload only one video i can return it with this code in the view.py:
def cours(request, id, slug):
c = Cours.objects.get(id=id, slug=slug)
p = Plan_simple.objects.get(cours=c)
return render(request, 'upload/cours.html', locals())
But when i upload two or more videos whith formset, and i change get fuction by filter it doesn't work:
def cours(request, id, slug):
c = Cours.objects.get(id=id, slug=slug)
p = Plan_simple.objects.filter(cours=c)
return render(request, 'upload/cours.html', locals())
the models.py
class Cours(models.Model):
titre = models.CharField(max_length=100)
slug = models.SlugField(max_length=100)
auteur = models.CharField(max_length=42)
comment = models.TextField(null=True)
link = models.CharField(max_length=100)
date = models.DateTimeField(default=timezone.now, verbose_name="Date de parution")
categorie = models.ForeignKey('Categorie', on_delete=models.CASCADE)
def save(self, *args, **kwargs):
self.slug = slugify(self.titre)
super(Cours, self).save(*args, **kwargs)
class Meta:
verbose_name = "cours"
db_table = "cours"
ordering = ['date']
class Plan_simple(models.Model):
partie = models.CharField(blank=True, max_length=100)
date = models.DateTimeField(default=timezone.now, verbose_name="Date de parution")
vid = models.FileField(upload_to='file/', blank=True, null = True)
cours = models.ForeignKey(Cours, related_name = "plan_simple", on_delete=models.CASCADE)
def __str__(self):
return self.partie
class Meta:
db_table = "plan_simple"
Can you help me?
Thanks
The issue is with this line. It does not request anything from the database. It only specifies a filter.
p = Plan_simple.objects.filter(cours=c)
You should change it to this...
p = Plan_simple.objects.filter(cours=c).all()

Django category view

I am new to django and maybe this is a stupid question but i got stuck with this for a while now.. so i have a few categories of meds, like AINS, antidepressants and each of this category has its own meds, and i am trying to show my users all the meds of a specific category: so if a users types in www.namesite.com/meds/AINS the it will show only the meds for that specific category .. AINS.I think that i should get the absolute url of every category and filter all the meds in that specific category?
Model:
class Category(models.Model):
category = models.CharField(max_length=30)
slug = models.SlugField()
def __str__(self):
return self.category
def get_absolute_url(self):
return reverse("meds", kwargs={'slug':self.category})
class Meta:
verbose_name_plural = 'Categorii'
class Medicament(models.Model):
title = models.CharField(max_length=50)
description = models.TextField(max_length=200)
category = models.ForeignKey(Category, on_delete='CASCADE')
price = models.DecimalField(decimal_places=2, max_digits=4)
prospect = models.TextField(default='Prospect')
company = models.TextField(default = 'company')
nr_unitati = models.IntegerField()
quantity = models.CharField(max_length=5, default='mg')
date_added = models.DateTimeField(auto_now_add=True)
rating = models.IntegerField(null=True, blank=True)
amount = models.IntegerField(default=0)
def __str__(self):
return self.title + ' ' + self.company + ' ' + str(self.nr_unitati) + ' ' + self.quantity
class Meta:
verbose_name_plural = 'Medicamente'
Views:
class MedCategoriesView(DetailView):
model = Category
template_name = 'products/AINS.html'
context_object_name = 'all_categories'
def get_context_data(self, **kwargs):
context = super(AINS_ListView, self).get_context_data(**kwargs)
context['meds'] = Medicament.objects.filter(category=self.object)
return context
Urls:
path('medicaments/<slug>/', MedCategoriesView.as_view(), name='meds'),
Using function based views.
def medicament(request, slug):
try:
medicaments = Medicament.objects.filter(category__slug=slug)
except Medicament.DoesNotExist:
raise Http404("Medicament does not exist")
return render(request, 'products/AINS.html', {'medicaments': medicaments})

Django ValueError when trying to save ManyToMany Values from a Form

I get the error "" needs to have a value for field "dataset" before this many-to-many relationship can be used." when trying to assign values to a ManyToMany field in my views. I've looked at many related questions here on SO that say I must save my Dataset object first. I think I am doing that...what is going wrong?? My database already contains four Subject items.
models.py
class Subject(TimeStampedModel):
subject_type = models.CharField(max_length=128, blank=False)
def __unicode__(self):
return self.subject_type
class Dataset(TimeStampedModel):
dataset_id = models.CharField(max_length=256)
dataset_doi = models.CharField(max_length=15)
dataset_name = models.CharField(max_length=256, blank=False)
dataset_description = models.TextField(blank=False)
lab = models.CharField(max_length=256, blank=False)
biological_sample = models.CharField(max_length=256, blank=False)
subject_type = models.ManyToManyField('Subject', related_name='datasets', blank=True)
date_collected = models.DateField(blank=True)
collection_facility = models.ManyToManyField('CollectionFacility', related_name='datasets', blank=True)
processing_notes = models.TextField(blank=True)
release_date = models.DateField()
release_asap = models.BooleanField()
pdb_code = models.CharField(max_length=256, blank=True)
publication_link = models.URLField(blank=True)
def create_name(self):
self.dataset_name = "%s %s" % (self.biological_sample, self.lab)
def save(self, *args, **kwargs):
self.dataset_id = self.id
def __unicode__(self):
return "%s : %s" % (self.dataset_name, self.dataset_id)
forms.py RegistrationForm:
class RegistrationForm(forms.Form):
subject_type = forms.ModelMultipleChoiceField(
label="Subject",
queryset = Subject.objects.all(),
widget=forms.CheckboxSelectMultiple(),
required = True,
)
views.py
def create_registration(form):
dataset = Dataset()
dataset.DOI = "preUpload"
dataset.lab = form.cleaned_data['lab']
dataset.biological_sample = form.cleaned_data['sample']
dataset.resource_type = form.cleaned_data['dataset_type']
dataset.dataset_description = form.cleaned_data['dataset_description']
dataset.date_collected = form.cleaned_data['date_collected']
dataset.release_date = form.cleaned_data['release_date']
dataset.release_asap = form.cleaned_data['release_asap']
if form.cleaned_data['pdb_code']:
dataset.pdb_code = form.cleaned_data['pdb_code']
if form.cleaned_data['publication_link']:
dataset.publication_link = form.cleaned_data['publication_link']
dataset.create_name()
dataset.save() # I don't think this save is working?
subjects = form.cleaned_data['subject_type']
dataset.subject_type = [x for x in subjects]
for facility in form.cleaned_data['facility']
dataset.collection_facility.add(facility)
dataset.save()
return dataset
def registration_submit(request):
registration_form = RegistrationForm(request.POST)
if registration_form.is_valid():
registration = create_registration(registration_form)
.......
You forgot to call the original save() in the overriden Dataset.save() method.
def save(self, *args, **kwargs):
self.dataset_id = self.id
super(Dataset, self).save(*args, **kwargs)

Filter data if it exists in an other model?

class WPArticle(models.Model):
title = models.TextField(unique=True)
content = models.TextField()
source = models.URLField() #article source
ctime = models.DateTimeField(auto_now_add=True)
mtime = models.DateTimeField(auto_now=True,auto_now_add=True)
post_tag = models.CharField(max_length=200)
category = models.CharField(max_length=200)
def __unicode__(self):
return self.title
class WPSendRecord(models.Model):
wpconf = models.ForeignKey(WPConf)
wparticle = models.ForeignKey(WPArticle)
ctime = models.TimeField(auto_now=True,auto_now_add=True)
def __unicode__(self):
return self.wparticle.title
I want to query out all the WPArticle which not in WPSendRecord? How to write the code?
You can use the exclude QuerySet method:
articles = WPArticle.objects.exclude(wpsendrecord__isnull=True)

How to always filter on a field on objects requests

I have two models :
class Album(models.Model):
#Attributes
title = models.CharField(max_length=200)
displayed = models.BooleanField()
created_on = models.DateTimeField(auto_now_add=True)
class Photos(models.Model):
#Attributes
title = models.CharField(max_length=500)
link = models.CharField(max_length=500)
album = models.ForeignKey(Album, unique=False, verbose_name=_('album'))
def upload_path(self, filename):
return 'upload/photos/%s/%s' % (self.id, filename)
def upload_path_thumbnail(self, filename):
return 'upload/photos/%s/%s' % (self.id, "thumnail_" +filename)
thumbnail = models.ImageField(upload_to=upload_path_thumbnail)
photo = models.ImageField(upload_to=upload_path)
created_on = models.DateTimeField(auto_now_add=True)
displayed = models.BooleanField()
And I want to force, when i select Photos, to always filter on displayed=1.
Thank you
Use a custom manager:
class DisplayedPhotoManager(models.Manager):
def get_queryset(self):
return super(DisplayedPhotoManager, self).get_queryset().filter(displayed=1)
class Photos(models.Model):
objects = DisplayedPhotoManager()
...
this will override standard "objects" manager (which can be dangerous).
A nicer pattern is often:
class DisplayedPhotoManager(models.Manager):
def get_queryset(self):
return super(DisplayedPhotoManager, self).get_queryset().filter(displayed=1)
class Photos(models.Model):
objects = models.Manager()
displayed = DisplayedPhotoManager()
...
and use 'displayed' instead of 'objects':
Photo.displayed.all()