Add a timestamp on a boolean field - django

I have a video object, which an administrator can feature. I want to be able to sort those featured videos by the date they were made featured.
Here are the models I currently have --
class VideoMedia(models.Model):
uploaded_by = models.ForeignKey('UserProfile')
video = models.ImageField(upload_to='videos')
info = models.ForeignKey('VideoInfo', blank = True, null=True)
class VideoInfo(models.Model):
title = models.CharField(max_length=256)
featured = models.BooleanField # need time also
...
My relevant view code looks like this --
video_set = VideoInfo.objects.all()
if sort == 'featured':
videos = video_set.filter(featured=1) # .order_by('timestamp') ?
I tried adding a FK to the featured field, but it makes it very difficult for me in the view/template to display the correct data.
class FeaturedVideos(models.Model):
video = models.ForeignKey(VideoMedia)
timestamp = models.DateTimeField(auto_now_add=True)
# in view
if sort == 'featured':
videos = FeaturedVideos.objects.order_by('timestamp')
# this doesn't work, because I need to be relative to the VideoInfo model
# for the information to display correctly in the template
What would be the most straightforward way to accomplish this task? Thank you.

In the past I have used a nullable datetimefield as a boolean. When it is null then you know it is false, and when it has a date you know it is true, and the date and time that field was set to True.
It is a cheap and easy way to get two uses out of one field. You can also add some simple properties to your model to make it easier when using templates. Here is a pretty quick example.
class VideoInfo(models.Model):
title = models.CharField(max_length=256)
featured = models.DateTimeField(null=True, blank=True)
#property
def is_featured(self):
if self.featured:
return True
else:
return False

Related

Django: what is the better way to get users info from models in view or template?

I have few django models and I want display some information the for several users in the template.
Below are the models:
class CustomUser(AbstractUser):
def __str__(self):
return self.email
class Post(models.Model):
author = models.ForeignKey(CustomUser,on_delete=models.CASCADE,)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
post_url = models.URLField(max_length = 200, blank = True)
slug = models.SlugField(unique=True, blank=True)
class subscription(models.Model):
creator = models.ForeignKey(CustomUser,default=None, null=True,on_delete=models.CASCADE,related_name='creator',)
booster = models.ForeignKey(CustomUser,default=None, null=True,on_delete=models.CASCADE,related_name='booster')
sub_value = models.FloatField(blank = True)
sub_id = models.TextField(blank = True)
status = models.BooleanField(default=False)
dateSubscribed = models.DateTimeField(default=timezone.now)
dateSubscriptionEnded = models.DateTimeField(default=timezone.now)
paymentCount = models.FloatField(default= 0)
I want to pass few users to template and display how many posts and subscriptions each user has? I am wondering what is the best way to do it? Is better number of posts and subscribers information in the view and just pass those things to template or pass users get that information in the template? Thanks!
Model => View => Template
Try to parse as much of the information from the model in the view as possible. The reason for this is the pure python in the view runs fast and is nicer to work with the pure python. So when I can I try to break down information in the view into lists of objects. So for your example.
determine what users you want and add them to a list then loop through the list filtering using the username or id.
ex:
Post.objects.filter(author='User')
then create a list of objects with the relevant user, post count, and sub info.
then pass this to the template you can loop through the list using all the relevant data in your objects.
hope that was clear and useful some of that is my own development bias there may be a better way but that's how I have approached a similar issue in the past. good luck!

Django all related data

class Docs(models.Model):
doc_id = models.BigIntegerField(primary_key=True)
journal = models.CharField(max_length=50, blank=True, null=True)
year = models.IntegerField(blank=True, null=True)
class Meta:
managed = False
db_table = 'docs'
class Assays(models.Model):
assay_id = models.BigIntegerField(primary_key=True)
doc = models.ForeignKey('Docs', models.DO_NOTHING)
description = models.CharField(max_length=4000, blank=True, null=True)
class Meta:
managed = False
db_table = 'assays'
class Activities(models.Model):
activity_id = models.BigIntegerField(primary_key=True)
assay = models.ForeignKey(Assays, models.DO_NOTHING)
doc = models.ForeignKey(Docs, models.DO_NOTHING, blank=True, null=True)
record = models.ForeignKey('CompoundRecords', models.DO_NOTHING)
class Meta:
managed = False
db_table = 'activities'
I apologize in advance if this answer is easily found elsewhere. I have searched all over and do not see a simple way to query my data as intuitively as I feel like should be possibe.
These are classes for 3 tables. The actual dataset is closer to 100 tables. Each doc_id can have one or many associated activity_ids. Each activity_id is associated with one assay_id.
My goal is to obtain all of the related data for each of the activities in a single doc. For instance:
query_activities_values = Docs.objects.get(doc_id=5535).activities_set.values()
for y in query_activities_values:
print(y)
break
>>> {'activity_id': 753688, 'assay_id': 158542, 'doc_id': 5535, .....
This returns 32 dictionaries (only part of the first is shown) for columns in the Activities table that have doc_id=5535. I would like to go one step further and also automatically pull in all of the data from the Assays table that is associated with the corresponding assay_id for each dictionary.
I can access that Assay data through a similar query, but only by stating each field explicitly:
query_activities_values = Docs.objects.get(doc_id=5535).activities_set.values('assay', 'assay__assay_type', 'assay__description')
for y in query_activities_values:
print(y)
break
I would like a single query that finds not only the assay and associated assay data for one activity_id, but finds all data and associated data for the 90+ other tables associated in the model
Thank you
Update 1
I did find this code that works surprisingly well for my needs, however, I was curious if this is the best method:
from django.forms.models import model_to_dict
def serial_model(modelobj):
opts = modelobj._meta.fields
modeldict = model_to_dict(modelobj)
for m in opts:
if m.is_relation:
foreignkey = getattr(modelobj, m.name)
if foreignkey:
try:
modeldict[m.name] = serial_model(foreignkey)
except:
pass
return modeldict
That's not too much code, but I thought there may be a more built-in way to do this.
What you need is prefetch_related:
Django 2.2 Prefetch Related Docs
query_activities_values = Docs.objects.get(doc_id=5535).activities_set.values()
Would become:
query_activities_values = Docs.objects.prefetch_related(models.Prefetch("activities_set", to_attr="activities"), models.Prefetch("assays_set", to_attr="assays")).get(doc_id=5535)
A new attributes will be created called "activities" and "assays" which you can use to retrieve data.
One more thing. This isn't actually 1 query. It's 3. However, if you're getting more than just one object from Docs, it's still going to be 3.
Also, is there a reason why you're using BigIntegerField?

django cms plugin that display model with specific value checked

I made a model that displays articles and when you create an article you have the possibility to choose if this article will be a featured one.
So this is basically what I have in my Article model :
class Article(ModelMeta, TranslatableModel):
taints_cache = True
"""
Press article element,
"""
date_created = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
date_realization = models.DateField(_('Realised in'),
default=timezone.now)
image = FilerImageField(verbose_name=_('Featured image'), blank=True,
null=True,
on_delete=models.SET_NULL,
related_name='image_press_article',
help_text=_('Set if the article will be featured'))
sources = models.ManyToManyField(ArticleSource, verbose_name=_('Source'),
blank=False, null=True, related_name='sources_press_article')
regions = models.ManyToManyField(Country, verbose_name=_('Country of the article'),
blank=True, null=True,
related_name='regions_press_article')
global_regions = models.BooleanField('Global', default=True)
featureArticle = models.BooleanField(_('Feature'), help_text=_('Feature this article'), default=False)
Then, I created a plugin that displays the featured articles.
But the thing is, in the django plugin admin I let the user the possibility to choose which article he wants to display (with a maximum of 3).
But in this choosing list, all my articles are listed.
What I want to, is to list only the articles that are checked as "featured", in my plugin admin. Instead of having all the articles.
Here what I have with my cms_plugin's model :
class FeaturedArticlePlugin(CMSPlugin):
selected_article = SortedManyToManyField(Article, blank=True, verbose_name=_('Selected articles'),
help_text=_('Select the featured articles to display'))
def __str__(self):
return u'%s Selected articles' % self.selected_article.all()
def copy_relations(self, oldinstance):
self.selected_article = oldinstance.selected_article.all()
And in my cms_plugins.py :
class PressPlugin(CMSPluginBase):
module = 'Press'
class PressFeaturedArticlePlugin(PressPlugin):
module = _('Press')
name = _('Press feature')
model = FeaturedArticlePlugin
render_template = 'djangocms_press/plugins/feature_article.html'
number_article = 3
def render(self, context, instance, placeholder):
"""
Get a list of selected_articles
"""
selected_article = instance.selected_article.all()
number_selected_article = selected_article.count()
feature_article_list = list(selected_article[:self.number_article])
context['instance'] = instance
context['feature_article_list'] = feature_article_list
return context
plugin_pool.register_plugin(PressFeaturedArticlePlugin)
So, I am sure it's nothing complicated but I can't point this out.
Anyone has a clue ?
EDIT
From what I understand, the only thing that concern the display of all articles is this line :
selected_article = SortedManyToManyField(Article, blank=True, verbose_name=_('Selected articles'),
help_text=_('Select the featured articles to display'))
So what I am suppose to do is to filter this selected_article with the featureArticle=True. But how to do it ?
I am not quite sure if I am missing something, but, couldn't you just apply a filter here?
selected_article = instance.selected_article.all().filter(featureArticle=true)
number_selected_article = selected_article.count()
Or is the problem with the lines after?
feature_article_list = list(selected_article[:self.number_article])
If your problem is selecting the extra articles, maybe you need to order them by date and select only the necessary?
feature_article_list = list(Articles.all().order_by('-created')[:self.number_article - number_selected_article]
Which will only select the extra necessaries?
Edit: Your situation kind of reminds me of a problem I once had. So I'll refer you to the same page that helped me in the past just in case you'd manage to figure it out.
Restrict django admin change permissions
Edit 2 : "I created a plugin that displays the featured articles. But the thing is, in the django plugin admin I let the user the possibility to choose which article he wants to display (with a maximum of 3). But in this choosing list, all my articles are listed."
Isn't it ok if all the articles are displayed there? How can you choose among them if they are not all displayed?

Django bulk edit form

In my project I have a many-to-one relation with one Serie having up to 20 samples. I'm trying to implement a system where a user uploads a (csv)file and is then sent to a page where they can fill in any missing data. I haven't found a way to implement this and was looking for some help. The idea is that I want a table with each row having 4 fields, which are linked to the sample in question and the table will have as many rows as there were samples in the (csv)file. Furthermore, if data is already present for one of the fields, I want it to prefill the field in question. In the end, the updated data is committed by pressing a single save button at the bottom so it's supposed to be one big form.
I've added the models below. The attributes which I want to update in the form are index, pool and remarks, which may be present in the csv file already but often they aren't.
Can anyone give me any tips on how to implement this or hint at methods which are best for implementing something like this?
Models
class Sample(models.Model):
name = models.CharField(max_length=20)
pool = models.ForeignKey(Pool, blank=True, null=True)
serie = models.ForeignKey(Serie, blank=True, null = True)
index = models.ForeignKey(Index, blank=True, null=True)
remarks = models.CharField(max_length=50, blank=True)
def __str__(self):
return self.name
class Serie(models.Model):
a_type = models.ForeignKey(Atype)
name = models.IntegerField()
def __str__(self):
return str(self.a_type)+'-'+str(self.name)
Views
def serie_edit(request,serie_id):
try:
serie = Serie.objects.get(pk=serie_id)
except Serie.DoesNotExist:
raise Http404
index_list = Index.objects.all()
sample_list = Sample.objects.filter(serie__id = serie_id)
return render(request, 'samples/serie_edit.html', {'serie':serie, 'sample_list':sample_list, 'index_list':index_list})

Django entry creating. Method in views/other file or as a method of model class

Django creating entry.
1) As seen in Django docs:
class Article(models.Model):
user = models.ForeignField(User)
title = models.CharField(#some_params)
content = models.CharField(#some_params)
date = models.DateTimeField(#some_params)
Then in my views I can:
new_article = Article(user=user, title="abc", content="xyz", date = datetime.utcnow())
new_article.save()
2) But it also can be done like by calling method within Article class, ie:
class Article(models.Model):
user = models.ForeignField(User)
title = models.CharField()
content = models.CharField()
def add_article(self, title, content):
self.title = title
self.content = content
self.date = datetime.utcnow()
self.save()
and then in views:
title = "abc"
content = "xyz"
new_article = Article(user=user)
new_article.add_article(abc, xyz)
I am asking because I have seen both ways of adding content into database. I would like to ask:
What is better practice?
Any concerns about security in 2nd example?
Option 1 is, in my opinion, better practice. add_article is unnecessary, because you can set the date by using the auto_now property of the date field, and everything else is already built-in. You'll have less code and less maintenance.