Django display additional info for items in a list - django

I've a problem and i don't know the right way to solve it.
Basically,i've a mode, called Task:
class Task(models.Model):
#mto1: many task made of one template
template = models.ForeignKey(Template)
STATUS_CHOISE = (('PR', 'In process'), ('ST', 'Stopped'), ('FN', 'Finished'), ('DL', 'Deleted'),)
status = models.CharField(max_length=2, choices=STATUS_CHOISE, default='ST')
responses_required = models.IntegerField(default=0)
date_deadline = models.DateTimeField(auto_now=False, auto_now_add=False)
date_created = models.DateTimeField(auto_now_add=True, auto_now=False)
which can have several answers
class Response(models.Model):
#mto1: many Responses generated for one task
task = models.ForeignKey(Template)
STATUS_CHOISE = (('PR', 'Process'), ('FN', 'Finished'))
status = models.CharField(max_length=2, choices=STATUS_CHOISE, default='ST')
date_finished= models.DateTimeField(auto_now_add=False, auto_now=True)
date_created = models.DateTimeField(auto_now_add=True, auto_now=False)
ip_address=models.IPAddressField()
now, i would like to display all the task of one user (which comes from the template model, and this is done) with additional information about the answers, which are
- number of answer give (so which status is = FN)
- number of total answer (status FN or PR)
- and maybe some extra info.
i did this
#login_required
def TemplateList(request):
task_list = Task.objects.filter(user=request.user)
return render_to_response('task_list.html',{'task_list':task_list}, context_instance=RequestContext(request))
but this just display the data present in the model, what about the value i've to compute?
so far i did it with CustomTag, but it doesn't seem a clean solution. i would rather do the logic in the view and then use the template just for display results.
But: how can i add this value to each item of the Task List?
do i have to do like in this: Passing additional data to a template in Django so create the objects from scratch (which requires me some logic in the template as well since i've to match the value in the list with the objects i crate)? or is there any better solution?
i tried generic view ,like list_detail.object_list
in this way
def TaskListDetail(request):
return list_detail.object_list(
request,
queryset = Task.objects.filter(user=request.user),
template_name = 'task_list.html',
template_object_name = 'task_list',
)
but first, it does not show anything (while the other view shows data), second i don't know how to add extra data in a way that they are matched with the item of the list.
any suggestion?

You can add a method to your model.
class Task(models.Model):
#mto1: many task made of one template
template = models.ForeignKey(Template)
STATUS_CHOISE = (('PR', 'In process'), ('ST', 'Stopped'), ('FN', 'Finished'), ('DL', 'Deleted'),)
status = models.CharField(max_length=2, choices=STATUS_CHOISE, default='ST')
responses_required = models.IntegerField(default=0)
date_deadline = models.DateTimeField(auto_now=False, auto_now_add=False)
date_created = models.DateTimeField(auto_now_add=True, auto_now=False)
def do_some_calculation(self):
#make funny things
return "foo"
In your template, you can access this with:
{% for taks in task_list %}
{{ task.do_some_calculation }}
{% endfor %}

Related

how to build query with several manyTomany relationships - Django

I really don't understand all the ways to build the right query.
I have the following models in the code i'm working on. I can't change models.
models/FollowUp:
class FollowUp(BaseModel):
name = models.CharField(max_length=256)
questions = models.ManyToManyField(Question, blank=True, )
models/Survey:
class Survey(BaseModel):
name = models.CharField(max_length=256)
followup = models.ManyToManyField(
FollowUp, blank=True, help_text='questionnaires')
user = models.ManyToManyField(User, blank=True, through='SurveyStatus')
models/SurveyStatus:
class SurveyStatus(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
survey = models.ForeignKey(Survey, on_delete=models.CASCADE)
survey_status = models.CharField(max_length=10,
blank=True,
null=True,
choices=STATUS_SURVEY_CHOICES,
)
models/UserSurvey:
class UserSurvey(BaseModel):
user = models.ForeignKey(User, null=True, blank=True,
on_delete=models.DO_NOTHING)
followups = models.ManyToManyField(FollowUp, blank=True)
surveys = models.ManyToManyField(Survey, blank=True)
questions = models.ManyToManyField(Question, blank=True)
#classmethod
def create(cls, user_id):
user = User.objects.filter(pk=user_id).first()
cu_quest = cls(user=user)
cu_quest.save()
cu_quest._get_all_active_surveys
cu_quest._get_all_followups()
cu_quest._get_all_questions()
return cu_quest
def _get_all_questions(self):
[[self.questions.add(ques) for ques in qstnr.questions.all()]
for qstnr in self.followups.all()]
return
def _get_all_followups(self):
queryset = FollowUp.objects.filter(survey__user=self.user).filter(survey__user__surveystatus_survey_status='active')
# queryset = self._get_all_active_surveys()
[self.followups.add(quest) for quest in queryset]
return
#property
def _get_all_active_surveys(self):
queryset = Survey.objects.filter(user=self.user,
surveystatus__survey_status='active')
[self.surveys.add(quest) for quest in queryset]
return
Now my questions:
my view sends to the create of the UserSurvey model in order to create a questionary.
I need to get all the questions of the followup of the surveys with a survey_status = 'active' for the user (the one who clicks on a button)...
I tried several things:
I wrote the _get_all_active_surveys() function and there I get all the surveys that are with a survey_status = 'active' and then the _get_all_followups() function needs to call it to use the result to build its own one. I have an issue telling me that
a list is not a callable object.
I tried to write directly the right query in _get_all_followups() with
queryset = FollowUp.objects.filter(survey__user=self.user).filter(survey__user__surveystatus_survey_status='active')
but I don't succeed to manage all the M2M relationships. I wrote the query above but issue also
Related Field got invalid lookup: surveystatus_survey_status
i read that a related_name can help to build reverse query but i don't understand why?
it's the first time i see return empty and what it needs to return above. Why this notation?
If you have clear explanations (more than the doc) I will very appreciate.
thanks
Quite a few things to answer here, I've put them into a list:
Your _get_all_active_surveys has the #property decorator but neither of the other two methods do? It isn't actually a property so I would remove it.
You are using a list comprehension to add your queryset objects to the m2m field, this is unnecessary as you don't actually want a list object and can be rewritten as e.g. self.surveys.add(*queryset)
You can comma-separate filter expressions as .filter(expression1, expression2) rather than .filter(expression1).filter(expression2).
You are missing an underscore in surveystatus_survey_status it should be surveystatus__survey_status.
Related name is just another way of reverse-accessing relationships, it doesn't actually change how the relationship exists - by default Django will do something like ModelA.modelb_set.all() - you can do reverse_name="my_model_bs" and then ModelA.my_model_bs.all()

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 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})

how to make URL pattern accept variable arguments in Django?

my title may not be very clear.
The problem I am facing now is:
my view passes arbitrary keyword arguments to another view.
This view handles with what info(keyword arguments it gets)
This is the example of search feature I am implementing.
Each user will have a list of Saved Searches. when they click on any one of the items in Search list, they will be directed to a different view that process the information it receives
In the Searches model, I have defined a get_absolute_url method that constructs the URL pattern of each of these search (based on models in the field).
my model:
class Searches(models.Model):
SELLER_CHOICES=(('OWNER','owner'),
('DEALER','dealer'),
('BOTH','both'), )
#search_id = models.IntegerField(primary_key=True)
user = models.ForeignKey(User)
make = models.CharField(max_length=100, blank=True)
model = models.CharField(max_length=100, blank=True)
keywords = models.CharField(max_length=100, blank=True)
max_price = models.IntegerField(blank=True, null=True)
min_price = models.IntegerField(blank=True, null=True)
max_year = models.IntegerField(blank=True, null=True)
min_year = models.IntegerField(blank=True, null=True)
pic_only = models.NullBooleanField()
search_title_only = models.NullBooleanField()
owner_dealer_all = models.CharField(max_length=10,choices=SELLER_CHOICES,verbose_name='owner/dealer')
class Meta:
#managed = False
db_table = 'Searches'
verbose_name_plural = "Searches"
def __unicode__(self):
return "%s %s %s-%s" %(self.make,self.model,self.max_year,self.min_year)
def get_absolute_url(self):
return reverse('postings.views.detail',args=[model_to_dict(self.object)])
view:
class SearchListView(ListView):
model=Searches
template:
{% extends "base.html" %}
{% block content %}
{% for obj in object_list %}
<p>{{ obj }}</p>
{% endfor %}
{% endblock %}
you can see from the image, when I click the your searches, I get error;
Reverse for 'postings.views.detail' with arguments '({'owner_dealer_all': u'DEALER', 'pic_only': True, 'make': u'toyota', u'id': 3, 'min_year': 1990, 'min_price': 4000, 'user': 1, 'keywords': u'hybrid', 'search_title_only': True, 'model': u'prius', 'max_price': 20000, 'max_year': 2012},)' and keyword arguments '{}' not found. 0 pattern(s) tried: []
Basically, I dont know how to handle this in the URL pattern.
OR
IF THIS IS A BAD DESIGN, PLEASE PLEASE SUGGEST A SOLUTION
If you really need to have all the variables in the URL, then you need to pass the variables as params of a GET query, so your URL will look like this:
http://example.com/search?owner_dealer_all=DEALER&pic_only=True&make=toyota&id=3&min_year=1990&min_price=4000&user=1&keywords=hybrid&search_title_only=True&model=prius&max_price=20000&max_year=2012
But, I would strongly suggest that you keep that URL as separate from the Search.get_absolute_url result, as the latter is supposed to point to the actual model. So have that function return something like:
http://example.com/search/23465
where the number is the ID for your Search model instance. In that view, get all the saved details and make a search on them. If you actually don't need the data in your URL, simply opt for the latter version only.

django many to many get attributes from other object

So I've been using django for a while now, and it's great. I've recently come across a little bit of a problem, and I'm sure there's a crappy way to get it to work, but what I've found with Django is that they've usually built in all sorts of mechanisms to do things for you. So what I'm not finding is this:
Here are my models:
class LandmarkGroup(models.Model):
Name = models.CharField(max_length=150)
Description = models.CharField(max_length=300, blank=True)
IsActive = models.BooleanField(default=True)
landmarks = models.ManyToManyField('Landmark', blank=True, null=True)
def __unicode__(self):
return self.Name
class Landmark(models.Model):
Name = models.CharField(max_length=150)
Description = models.CharField(max_length=300, blank=True)
Polygon = models.PolygonField()
IsActive = models.BooleanField(default=True)
objects = models.GeoManager()
def __unicode__(self):
return self.Name
I also have another model 'Team' that has a ManyToMany with LandmarkGroup, but I'm not going to post it here. I have a view where I query for all the landmarks that have a landmarkgroup that has a team with the same team id as the one I passed in:
def mobile_startup(request):
...
landmarkGroups = LandmarkGroup.objects.filter(team=device.team, IsActive=True)
landmarks = Landmark.objects.filter(landmarkgroup__team=device.team, IsActive=True)
...
return render_to_response('webservice/mobile_startup.html', {'landmarks': landmarks, 'landmarkGroups': landmarkGroups})
Everything works, the only problem I'm having is, I'm returning this all as JSON to the mobile app, and I want to provide the landmarkGroup id for the landmark, so in my template I've been trying to:
"landmarkGroup" : {{ landmark.landmarkgroup.id }} }
but that's not working. Does anyone know any way I can get the landmarkGroup ID for each landmark in my set? Do I need to extract it when I do the query? I know I can reference each landmarkGroup in the query because I can do 'landmarkgroup__team=device.team', but I need to able to reference this object in the template
LandmarkGroup.landmarksis a ManyToManyField,therefore one Landmark can belong to multiple groups.
You should be able to output them in your template like this:
{% for group in landmark.landmarkgroup_set.all %}{{ group.pk }}{% endfor %}
The first group belonging to the landmark should be accessible through {% landmark.landmarkgroup_set.all.0 %}