samedi 29 novembre 2014

Relation inverse de Django requête sans clé étrangère - Stack Overflow


I'm currently working on a Django library to manage images of multiple resolutions (django-multires) where I am stuck optimizing a reserve relationship query. Before I explain the issue, let me try to explain what I am trying to achieve.


Background


The idea is to store multiple resolutions of an image however keep references to the original image in terms of image paths instead of foreign keys. I think an example will make more sense:


# the goal is to store multiple resolutions for 'image' field
class FooModel(models.Model):
image = MultiresImageField(...)

# MultiresImage.source will be the identical to FooModel.image
# so MultiresImage.source will act sort of like a foreign key
class MultiresImage(models.Model):
source = models.ImageField(...)
...

Using this approach instead of using a foreign key (or generic foreign key) to link to the source image allows to add multiple MultiresImageFields to the source model:


class FooModel(models.Model):
image = MultiresImageField(...)
image2 = MultiresImageField(...)

Now lets say you need to get all different resolutions for an image field within the source model:


foo = FooModel(...)
foo.image.get_all_multires_images()
# which behind the scenes will do something similar to
return MultiresImage.objects.filter(source=foo.image.name)

That works well until you need to query multiple FooModel instances in which case for each model instance I am forced to do a db lookup to get all resolutions for that model:


sources = FooModel.objects.filter(...)
for source in sources:
# this incurs a db query
foo.image.get_all_multires_images()

Usually I would use prefetch_related to do the performance optimization however in here I can't because my multires model does not have a foreign key to the source model hence reverse relationship does not exist on the source model.


Question


So my question is how can the above query be optimized?


Some current thoughts



  • Since I am making a custom model field, I could use contribute_to_class to manually add a reverse relationship to source model however I can't figure out how?

  • Another though is to use Prefetch API in Django>=1.7 but I can't figure out how to make that work as well.




The easiest, but probably not most elegant solution would be to write a kind of helper class:


def prefetch_related_images(image_queryset):
multires_images = MultiresImage.objects.filter(source__in=[image.name for image in image_queryset ])
for image in image_queryset:
image.multires_images = []
for multires_image in multires_images:
if multires_image.source == image.name:
image.multires_images.append(multires_image)

And well, a more elegant solution could be along the lines on your thought on contribute_to_class. Why don't you try something like a Generic Relationship:


class MultiresImage(models.Model):
source = models.ImageField(...)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
image_target= GenericForeignKey('content_type', 'object_id')

and then amend contribute_to_class like that:


def contribute_to_class(self, cls, name):
"""
Attached necessary garbage collection signals.
"""
super(MultiresImageField, self).contribute_to_class(cls, name)

setattr(cls,'%_source', GenericRelation(MultiresImage)

And then handle the details of managing the relationship via the signals (as you already do).



I'm currently working on a Django library to manage images of multiple resolutions (django-multires) where I am stuck optimizing a reserve relationship query. Before I explain the issue, let me try to explain what I am trying to achieve.


Background


The idea is to store multiple resolutions of an image however keep references to the original image in terms of image paths instead of foreign keys. I think an example will make more sense:


# the goal is to store multiple resolutions for 'image' field
class FooModel(models.Model):
image = MultiresImageField(...)

# MultiresImage.source will be the identical to FooModel.image
# so MultiresImage.source will act sort of like a foreign key
class MultiresImage(models.Model):
source = models.ImageField(...)
...

Using this approach instead of using a foreign key (or generic foreign key) to link to the source image allows to add multiple MultiresImageFields to the source model:


class FooModel(models.Model):
image = MultiresImageField(...)
image2 = MultiresImageField(...)

Now lets say you need to get all different resolutions for an image field within the source model:


foo = FooModel(...)
foo.image.get_all_multires_images()
# which behind the scenes will do something similar to
return MultiresImage.objects.filter(source=foo.image.name)

That works well until you need to query multiple FooModel instances in which case for each model instance I am forced to do a db lookup to get all resolutions for that model:


sources = FooModel.objects.filter(...)
for source in sources:
# this incurs a db query
foo.image.get_all_multires_images()

Usually I would use prefetch_related to do the performance optimization however in here I can't because my multires model does not have a foreign key to the source model hence reverse relationship does not exist on the source model.


Question


So my question is how can the above query be optimized?


Some current thoughts



  • Since I am making a custom model field, I could use contribute_to_class to manually add a reverse relationship to source model however I can't figure out how?

  • Another though is to use Prefetch API in Django>=1.7 but I can't figure out how to make that work as well.



The easiest, but probably not most elegant solution would be to write a kind of helper class:


def prefetch_related_images(image_queryset):
multires_images = MultiresImage.objects.filter(source__in=[image.name for image in image_queryset ])
for image in image_queryset:
image.multires_images = []
for multires_image in multires_images:
if multires_image.source == image.name:
image.multires_images.append(multires_image)

And well, a more elegant solution could be along the lines on your thought on contribute_to_class. Why don't you try something like a Generic Relationship:


class MultiresImage(models.Model):
source = models.ImageField(...)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
image_target= GenericForeignKey('content_type', 'object_id')

and then amend contribute_to_class like that:


def contribute_to_class(self, cls, name):
"""
Attached necessary garbage collection signals.
"""
super(MultiresImageField, self).contribute_to_class(cls, name)

setattr(cls,'%_source', GenericRelation(MultiresImage)

And then handle the details of managing the relationship via the signals (as you already do).


PostgreSQL - requête de django, distinct sur une clé étrangère et commande par un autre attribut - Stack Overflow


I got stuck in a query in django. I have two models,


Class Course(models.Model):
provider = ForeignKey(Provider)
rating = FloatField()

Class Provider(models.Model):
...

I want to query a list of courses, but no two courses can be provided by the same provider. that is, only the most relevant course from each provider is selected. I did this,


Course.objects.filter(xxxx).distinct('provider')

This works OK, but if I want to add order_by to this query, like


Course.objects.filter(xxxx).distinct('provider').order_by('rating')

an error occurs. In django documentation, the fields in order_by() must start with the fields in distinct(), in the same order.


yet, I still cannot find any other workarounds to do the same thing.


any ideas? Thank you so much.




You need to look at this problem from the 'reverse' perspective and use "annotage". Here is how you'll get your desired output in a view:


#views.py
from xxx.models import Course, Provider
from django.db.models import Min

from django.shortcuts import render

def home(request):
t = Provider.objects.annotate(best_rating = Min('course__rating')).filter('xxx').order_by('best_rating')

return render(request, 'home.html', {
't':t,
})

So what's happening here:


First of all "annotate" is Django's way to do what is generally known as "group by" statements. Unfortunately they delivery different results depending on what object they are called upon. So in our case we have to look at "the best course of each provider" instead of "top rated courses and their providers".


In our .annotate(best_rating = Min('course__rating')) statement, the inner clause returns the best course (assuming 1.0 Rating is the best, use Max() if it is the opposite way around). The return value is assigned to a virtual model attribute called best_rating, which you can call in a template like any other model member. It just won't be stored in the database.


The String 'course__rating' is a special string. It tells Django ORM what field we want to find the minimum of. This string has the format "<MODEL>__<FIELD>". Although a provider is not aware of his relationship to a course, Django will do this reverse lookup for us. So this string basically says: "give me all rating fields of courses that have a relationship with providers"


annotate returns a QuerySet like many other querySet Methods, hence you can filter and order the new set as you please.


Of course you can filter before the annotation as well, but be aware this might affect your final result when you do aggregations like finding a min() or max() value.


Basic template example:


     #home.html
{% for e in t %}
{{ e.name }} {{ e.best_rating }}<br>
{% endfor %}

Have a look at the Django Documentation for further information about annotations and reverse lookups.


Update 01.04.2014: If you want to keep your Query driven by a list of Courses, you can use the following statement using F() Statements


from xxx.models import Course, Provider
from django.db.models import Min, F
from django.shortcuts import render

def home(request):
t = Course.objects.annotate(best_rating = Min('provider__course__rating')).filter(rating = F('best_rating'))

return render(request, 'home.html', {
't':t,
})

This Query will annotate by providers and course ratings. But this alone would return all providers with an additional column with the lowest rating of a course. So we need to filter each row on this new value. To do this, we need a F() Expression, that matches a value for each row.



I got stuck in a query in django. I have two models,


Class Course(models.Model):
provider = ForeignKey(Provider)
rating = FloatField()

Class Provider(models.Model):
...

I want to query a list of courses, but no two courses can be provided by the same provider. that is, only the most relevant course from each provider is selected. I did this,


Course.objects.filter(xxxx).distinct('provider')

This works OK, but if I want to add order_by to this query, like


Course.objects.filter(xxxx).distinct('provider').order_by('rating')

an error occurs. In django documentation, the fields in order_by() must start with the fields in distinct(), in the same order.


yet, I still cannot find any other workarounds to do the same thing.


any ideas? Thank you so much.



You need to look at this problem from the 'reverse' perspective and use "annotage". Here is how you'll get your desired output in a view:


#views.py
from xxx.models import Course, Provider
from django.db.models import Min

from django.shortcuts import render

def home(request):
t = Provider.objects.annotate(best_rating = Min('course__rating')).filter('xxx').order_by('best_rating')

return render(request, 'home.html', {
't':t,
})

So what's happening here:


First of all "annotate" is Django's way to do what is generally known as "group by" statements. Unfortunately they delivery different results depending on what object they are called upon. So in our case we have to look at "the best course of each provider" instead of "top rated courses and their providers".


In our .annotate(best_rating = Min('course__rating')) statement, the inner clause returns the best course (assuming 1.0 Rating is the best, use Max() if it is the opposite way around). The return value is assigned to a virtual model attribute called best_rating, which you can call in a template like any other model member. It just won't be stored in the database.


The String 'course__rating' is a special string. It tells Django ORM what field we want to find the minimum of. This string has the format "<MODEL>__<FIELD>". Although a provider is not aware of his relationship to a course, Django will do this reverse lookup for us. So this string basically says: "give me all rating fields of courses that have a relationship with providers"


annotate returns a QuerySet like many other querySet Methods, hence you can filter and order the new set as you please.


Of course you can filter before the annotation as well, but be aware this might affect your final result when you do aggregations like finding a min() or max() value.


Basic template example:


     #home.html
{% for e in t %}
{{ e.name }} {{ e.best_rating }}<br>
{% endfor %}

Have a look at the Django Documentation for further information about annotations and reverse lookups.


Update 01.04.2014: If you want to keep your Query driven by a list of Courses, you can use the following statement using F() Statements


from xxx.models import Course, Provider
from django.db.models import Min, F
from django.shortcuts import render

def home(request):
t = Course.objects.annotate(best_rating = Min('provider__course__rating')).filter(rating = F('best_rating'))

return render(request, 'home.html', {
't':t,
})

This Query will annotate by providers and course ratings. But this alone would return all providers with an additional column with the lowest rating of a course. So we need to filter each row on this new value. To do this, we need a F() Expression, that matches a value for each row.


Logique de mauvaise requête Django Q - Stack Overflow


I'm trying to create a manager that has a method 'active_or_users' to retrieve all accounts that are active, or that an user has created. An active account has a start date that is either today, or somewhere in the past, and a end date that is somewhere in the future. Right now the active_or_users method works, however it returns duplicates of the same object. It's returning three copies of a user created active job. This is less than ideal.


from django.db.models import Q
from django.db import models
from django.contrib.auth.models import User

class ActiveJobs(models.Manager):
def active(self):
return super(ActiveJobs, self).get_query_set().\
filter(publications__publish_on__lte=date.today(),
publications__end_on__gt=date.today())

def active_or_users(self, user):
return super(ActiveJobs, self).get_query_set().\
filter((Q(publications__publish_on__lte=date.today()) &
Q(publications__end_on__gt=date.today())) | Q(creator=user))

class Job(models.Model):
title = models.CharField(max_length=100)
slug = models.SlugField(blank=True, null=True)
creator = models.ForeignKey(User)
objects = ActiveJobs()


class JobPublicationRecord(models.Model):
job = models.ForeignKey('Job', related_name='publications')
publish_on = models.DateField(auto_now=False)
end_on = models.DateField(auto_now=False, auto_now_add=False,
blank=True, null=True)



To put the comments into an answer


With the OR query, an instance will be returned for every hit of the query. I.e: an instance if a Job is created by user and another instance of the same job if also in the date range specified, etc.


So to fix this, change the method active_or_users to:


def active_or_users(self, user):
return super(ActiveJobs, self).get_query_set().filter(
(Q(publications__publish_on__lte=date.today()) &
Q(publications__end_on__gt=date.today())) | Q(creator=user)).distinct()


I'm trying to create a manager that has a method 'active_or_users' to retrieve all accounts that are active, or that an user has created. An active account has a start date that is either today, or somewhere in the past, and a end date that is somewhere in the future. Right now the active_or_users method works, however it returns duplicates of the same object. It's returning three copies of a user created active job. This is less than ideal.


from django.db.models import Q
from django.db import models
from django.contrib.auth.models import User

class ActiveJobs(models.Manager):
def active(self):
return super(ActiveJobs, self).get_query_set().\
filter(publications__publish_on__lte=date.today(),
publications__end_on__gt=date.today())

def active_or_users(self, user):
return super(ActiveJobs, self).get_query_set().\
filter((Q(publications__publish_on__lte=date.today()) &
Q(publications__end_on__gt=date.today())) | Q(creator=user))

class Job(models.Model):
title = models.CharField(max_length=100)
slug = models.SlugField(blank=True, null=True)
creator = models.ForeignKey(User)
objects = ActiveJobs()


class JobPublicationRecord(models.Model):
job = models.ForeignKey('Job', related_name='publications')
publish_on = models.DateField(auto_now=False)
end_on = models.DateField(auto_now=False, auto_now_add=False,
blank=True, null=True)


To put the comments into an answer


With the OR query, an instance will be returned for every hit of the query. I.e: an instance if a Job is created by user and another instance of the same job if also in the date range specified, etc.


So to fix this, change the method active_or_users to:


def active_or_users(self, user):
return super(ActiveJobs, self).get_query_set().filter(
(Q(publications__publish_on__lte=date.today()) &
Q(publications__end_on__gt=date.today())) | Q(creator=user)).distinct()

python - Django précédente et suivante objets par titre à l'aide de modèles - Stack Overflow


I want to show a link to the previous lesson and next lesson according to the title. I'm trying to do this in my models by using get_next_by_title.


Please point me in the right direction if there is a simpler way or if there is official documentation for using custom get_next_or_prev_by_FIELD.


Using Django 1.6.


Here is my models.py.


class Lesson(models.Model):
tutorials = models.ForeignKey('Tutorial', blank=True)
title = models.CharField(max_length=65)
slug = models.SlugField(unique=True)

def __unicode__(self, ):
return self.title

class Meta:
ordering = 'title',

def get_absolute_url(self):
return reverse('lesson', args=[str(self.slug)])

def get_next_by_title(self):
try:
return self._get_next_or_previous_by_FIELD('title', is_next=True)
except Lesson.DoesNotExist:
return None

def get_previous_by_title(self):
try:
return self._get_next_or_previous_by_FIELD('title', is_next=False)
except Lesson.DoesNotExist:
return None

Here is my template.


   {% with prev_lesson=lesson.get_previous_by_title %}
{% if prev_lesson %}
<a class="col-md-6" href="{{ prev_lesson.get_absolute_url }}">&laquo; {{ prev_lesson.title }}</a>
<div class="col-md-6"></div>
{% endif %} {% endwith %} {% with next_lesson=lesson.get_next_by_title %}
{% if next_lesson %}
<a class="col-md-6" href="{{ next_lesson.get_absolute_url }}">&laquo; {{ next_lesson.title }}</a>
{% endif %} {% endwith %}

Here is the full Traceback as requested.


Environment:


Request Method: GET
Request URL: /tutorials/lesson/lesson-name/

Django Version: 1.6.2
Python Version: 2.7.6
Installed Applications:
('django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
'ckeditor',
'tutorials')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware')
Template error:
In template C:\Users\Shaun\Desktop\sg\static\templates\tutorials\lesson.html, error at line 22
'str' object has no attribute 'attname'
12 : {% endif %}


13 : {% if lesson.get_next_by_timestamp %}


14 : <a class="right" href="{{ lesson.get_next_post.get_absolute_url }}">{{ lesson.get_next_post.title|truncatewords:'4' }} &raquo;</a>


15 : {% endif %}


16 :


17 : <div class='clearfix'></div>


18 :


19 : <h2>{{ lesson.title|upper }}</h2>


20 : <p>{{ lesson.content|safe }}</p>


21 :


22 : <a class="col-md-6" href=" {{ lesson.get_previous_by_title.get_absolute_url }} " title="{% trans "View previous post" %}">&laquo; {{ lesson.get_previous_by_title.title }}</a>


23 : <a class="col-md-6" href="{{ lesson.get_next_by_title.get_absolute_url }}" title="{% trans "View previous post" %}">&laquo; {{ lesson.get_next_by_title.title }}</a>


24 :


25 : {% endblock %}

Traceback:
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\core\handlers\base.py" in get_response
114. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Shaun\Desktop\sg\src\tutorials\views.py" in single_lesson
13. return render_to_response('tutorials/lesson.html', locals(), context_instance=RequestContext(request))
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\shortcuts\__init__.py" in render_to_response
29. return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\loader.py" in render_to_string
169. return t.render(context_instance)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in render
140. return self._render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in _render
134. return self.nodelist.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in render
840. bit = self.render_node(node, context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\debug.py" in render_node
78. return node.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\loader_tags.py" in render
123. return compiled_parent._render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in _render
134. return self.nodelist.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in render
840. bit = self.render_node(node, context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\debug.py" in render_node
78. return node.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\loader_tags.py" in render
62. result = block.nodelist.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in render
840. bit = self.render_node(node, context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\debug.py" in render_node
78. return node.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\debug.py" in render
88. output = self.filter_expression.resolve(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in resolve
585. obj = self.var.resolve(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in resolve
735. value = self._resolve_lookup(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in _resolve_lookup
789. current = current()
File "C:\Users\Shaun\Desktop\sg\src\tutorials\models.py" in get_previous_by_title
64. return self._get_next_or_previous_by_FIELD('title', is_next=False)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\db\models\base.py" in _get_next_or_previous_by_FIELD
708. param = force_text(getattr(self, field.attname))

Exception Type: AttributeError at /tutorials/lesson/setting-up-your-django-blog-application/
Exception Value: 'str' object has no attribute 'attname'



Django DateTimeField add the get_previous_by_ only. If you want by title you must create your own methods. It doesn't show anything because Django template system fails silently.


Django Model class has a _get_next_or_previous_by_FIELD, and you can create the following:


class MyModel(models.Model):
[fields]

def get_next_by_title(self):
try:
return self._get_next_or_previous_by_FIELD('title', is_next=True)
except MyModel.DoesNotExist:
return None

def get_previous_by_title(self):
try:
return self._get_next_or_previous_by_FIELD('title', is_next=False)
except MyModel.DoesNotExist:
return None

Template:


  <a class="col-md-6" href="{{ lesson.get_previous_by_title.get_absolute_url }}" title="{% trans "View previous post" %}">&laquo; {{ lesson.get_previous_by_title.title }}</a>
<a class="col-md-6" href="{{ lesson.get_next_by_title.get_absolute_url }}" title="{% trans "View previous post" %}">&laquo; {{ lesson.get_next_by_title.title }}</a>


I want to show a link to the previous lesson and next lesson according to the title. I'm trying to do this in my models by using get_next_by_title.


Please point me in the right direction if there is a simpler way or if there is official documentation for using custom get_next_or_prev_by_FIELD.


Using Django 1.6.


Here is my models.py.


class Lesson(models.Model):
tutorials = models.ForeignKey('Tutorial', blank=True)
title = models.CharField(max_length=65)
slug = models.SlugField(unique=True)

def __unicode__(self, ):
return self.title

class Meta:
ordering = 'title',

def get_absolute_url(self):
return reverse('lesson', args=[str(self.slug)])

def get_next_by_title(self):
try:
return self._get_next_or_previous_by_FIELD('title', is_next=True)
except Lesson.DoesNotExist:
return None

def get_previous_by_title(self):
try:
return self._get_next_or_previous_by_FIELD('title', is_next=False)
except Lesson.DoesNotExist:
return None

Here is my template.


   {% with prev_lesson=lesson.get_previous_by_title %}
{% if prev_lesson %}
<a class="col-md-6" href="{{ prev_lesson.get_absolute_url }}">&laquo; {{ prev_lesson.title }}</a>
<div class="col-md-6"></div>
{% endif %} {% endwith %} {% with next_lesson=lesson.get_next_by_title %}
{% if next_lesson %}
<a class="col-md-6" href="{{ next_lesson.get_absolute_url }}">&laquo; {{ next_lesson.title }}</a>
{% endif %} {% endwith %}

Here is the full Traceback as requested.


Environment:


Request Method: GET
Request URL: /tutorials/lesson/lesson-name/

Django Version: 1.6.2
Python Version: 2.7.6
Installed Applications:
('django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
'ckeditor',
'tutorials')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware')
Template error:
In template C:\Users\Shaun\Desktop\sg\static\templates\tutorials\lesson.html, error at line 22
'str' object has no attribute 'attname'
12 : {% endif %}


13 : {% if lesson.get_next_by_timestamp %}


14 : <a class="right" href="{{ lesson.get_next_post.get_absolute_url }}">{{ lesson.get_next_post.title|truncatewords:'4' }} &raquo;</a>


15 : {% endif %}


16 :


17 : <div class='clearfix'></div>


18 :


19 : <h2>{{ lesson.title|upper }}</h2>


20 : <p>{{ lesson.content|safe }}</p>


21 :


22 : <a class="col-md-6" href=" {{ lesson.get_previous_by_title.get_absolute_url }} " title="{% trans "View previous post" %}">&laquo; {{ lesson.get_previous_by_title.title }}</a>


23 : <a class="col-md-6" href="{{ lesson.get_next_by_title.get_absolute_url }}" title="{% trans "View previous post" %}">&laquo; {{ lesson.get_next_by_title.title }}</a>


24 :


25 : {% endblock %}

Traceback:
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\core\handlers\base.py" in get_response
114. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Shaun\Desktop\sg\src\tutorials\views.py" in single_lesson
13. return render_to_response('tutorials/lesson.html', locals(), context_instance=RequestContext(request))
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\shortcuts\__init__.py" in render_to_response
29. return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\loader.py" in render_to_string
169. return t.render(context_instance)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in render
140. return self._render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in _render
134. return self.nodelist.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in render
840. bit = self.render_node(node, context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\debug.py" in render_node
78. return node.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\loader_tags.py" in render
123. return compiled_parent._render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in _render
134. return self.nodelist.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in render
840. bit = self.render_node(node, context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\debug.py" in render_node
78. return node.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\loader_tags.py" in render
62. result = block.nodelist.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in render
840. bit = self.render_node(node, context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\debug.py" in render_node
78. return node.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\debug.py" in render
88. output = self.filter_expression.resolve(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in resolve
585. obj = self.var.resolve(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in resolve
735. value = self._resolve_lookup(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in _resolve_lookup
789. current = current()
File "C:\Users\Shaun\Desktop\sg\src\tutorials\models.py" in get_previous_by_title
64. return self._get_next_or_previous_by_FIELD('title', is_next=False)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\db\models\base.py" in _get_next_or_previous_by_FIELD
708. param = force_text(getattr(self, field.attname))

Exception Type: AttributeError at /tutorials/lesson/setting-up-your-django-blog-application/
Exception Value: 'str' object has no attribute 'attname'


Django DateTimeField add the get_previous_by_ only. If you want by title you must create your own methods. It doesn't show anything because Django template system fails silently.


Django Model class has a _get_next_or_previous_by_FIELD, and you can create the following:


class MyModel(models.Model):
[fields]

def get_next_by_title(self):
try:
return self._get_next_or_previous_by_FIELD('title', is_next=True)
except MyModel.DoesNotExist:
return None

def get_previous_by_title(self):
try:
return self._get_next_or_previous_by_FIELD('title', is_next=False)
except MyModel.DoesNotExist:
return None

Template:


  <a class="col-md-6" href="{{ lesson.get_previous_by_title.get_absolute_url }}" title="{% trans "View previous post" %}">&laquo; {{ lesson.get_previous_by_title.title }}</a>
<a class="col-md-6" href="{{ lesson.get_next_by_title.get_absolute_url }}" title="{% trans "View previous post" %}">&laquo; {{ lesson.get_next_by_title.title }}</a>

Django prefetch_related id seulement - Stack Overflow


I'm trying to optimise my queries but prefetch_related insists on joining the tables and selecting all the fields even though I only need the list of ids from the relations table.


queries


You can ignore the 4th query. It's not related to the question.


Related Code:


class Contact(models.Model):
...
Groups = models.ManyToManyField(ContactGroup, related_name='contacts')
...

queryset = Contact.objects.all().prefetch_related('Groups')


I'm trying to optimise my queries but prefetch_related insists on joining the tables and selecting all the fields even though I only need the list of ids from the relations table.


queries


You can ignore the 4th query. It's not related to the question.


Related Code:


class Contact(models.Model):
...
Groups = models.ManyToManyField(ContactGroup, related_name='contacts')
...

queryset = Contact.objects.all().prefetch_related('Groups')

Heroku - Django powered site avec plusieurs sites de micro-ce que je dois créer un projet distinct pour chaque microsite ? -Débordement de pile


I'm looking to build a Django website with the main site on example.com. On this domain, a user can register using an email and password and start writing blog posts at example.com/conversations. Admins will be able to login into the Django Admin to alter posts and change content on the other pages of example.com.


The website will have one microsite each year on subdomains, e.g., 2013.example.com, 2014.example.com, etc. Admins will be able to edit content using the Django Admin.


I'm going to deploy the Django project onto Heroku.


The question that I would answered is whether I should create a new Django app and Heroku deployment for each microsite and the main site? Or, whether I can create it all as one Django project?


The latter seems to make more sense to me, but unsure how I would go about it.



I'm looking to build a Django website with the main site on example.com. On this domain, a user can register using an email and password and start writing blog posts at example.com/conversations. Admins will be able to login into the Django Admin to alter posts and change content on the other pages of example.com.


The website will have one microsite each year on subdomains, e.g., 2013.example.com, 2014.example.com, etc. Admins will be able to edit content using the Django Admin.


I'm going to deploy the Django project onto Heroku.


The question that I would answered is whether I should create a new Django app and Heroku deployment for each microsite and the main site? Or, whether I can create it all as one Django project?


The latter seems to make more sense to me, but unsure how I would go about it.


jQuery - Django - poster un commentaire en utilisant Ajax - Stack Overflow


I'm trying to post a very simple comment with Ajax, when I'm not using Ajax the comment is posted and saved to the database just fine.


So far I've encountered 501 and 403 errors and all sorts of unwanted behaviour. I've tried to follow these instructions and I've read several answers on a similar topic on stackoverflow, but was unable to apply those solutions to my problem.


I'm really stuck here so any help would be greatly appreciated.


Relevant models.py:


class Photo(models.Model):
image = models.ImageField(
'image path', upload_to='images/%Y/%m/%d')
image_thumb = models.ImageField(
'thumbnail path', upload_to='images/thumbnails/%Y/%m/%d')
name = models.CharField(max_length=100)
description = models.CharField(max_length=150)
avg_rating = models.FloatField('average rating', default=5.1)

def __unicode__(self):
return self.description

class Comment(models.Model):
post_date = models.DateTimeField('posted')
comment_text = models.TextField(max_length=500)
photo = models.ForeignKey(Photo)

def __unicode__(self):
return self.comment_text

The comment form from forms.py:


class CommentForm(forms.Form):
comment_text = forms.CharField(widget=forms.Textarea)

And the view which normally handles comments in views.py:


def details(request, photo_id):
photo = get_object_or_404(Photo, pk=photo_id)
ratings_list = photo.rating_set.all().order_by('-id')

if request.method == 'POST':
form_c = CommentForm(request.POST)

if form_c.is_valid():
new_comment = Comment(
post_date = datetime.now(),
comment_text = form_c.cleaned_data['comment_text'],
photo = photo
)
new_comment.save()
if request.is_ajax():
return "???"
else:
return HttpResponseRedirect(reverse('photos:details', args= (photo_id,)))
else:
form_c = CommentForm()

return render(request, 'photos/details.html',
{'photo': photo, 'ratings_list': ratings_list[:5],
'form_c': form_c})

I've put question marks in there since by now I have no idea where should I redirect.


Relevant details.html template snippet:


<div id="commentSection">
{% for c in photo.comment_set.all %}
<p>On {{c.post_date|date:"dS \o\f F, \a\t H:i"}}, someone said: </p>
<p>{{c.comment_text}}</p>
<br>
{% endfor %}
</div>
<form id="commentForm" name="commentForm" action="{% url 'photos:details' photo.id %}" method="post">
{% csrf_token %}
<p>{{form_c.non_field_errors}}
{{form_c.comment_text.label_tag}}
{{form_c.comment_text.errors}}</p>
<p>{{form_c.comment_text}}</p>
<input type="submit" value="Post Comment" />
</form>

The urls.py:


from django.conf.urls import patterns, url
from photos import views

urlpatterns = patterns('',
url(r'^rate/(?P<photo_id>\d+)/$', views.rate, name='rate'),
url(r'^(?P<photo_id>\d+)/$', views.details, name='details'),
url(r'^$', views.index, name='index'),
)

I've added this script to avoid having the csrf validation fail when trying to submit comments via Ajax.


<script type="text/javascript">
$(document).ajaxSend(function(event, xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function sameOrigin(url) {
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
function safeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
});

And this is the Ajax part I've been struggling with today and yesterday:


$(document).ready(function() {
$('#commentForm').on('submit', function(e){
e.preventDefault();
var form = $(this);
$.ajax(
???
});
});
});

Thank you for your time.




You can't redirect from an Ajax post. In fact, the whole point of doing Ajax at all is to prevent the need for redirecting. You need to actually return some data: the usual way to do that is to return some JSON indicating what happens. If the form was valid and the save succeeded, you might just return an empty response: but if the form was not valid, you'll need to serialize the errors and return that as a JSON dict.


Then, in your Ajax script itself, you'll need to process that information and display it to the user. Your Ajax function should look something like:


var form = $(this);
$.post(form.attr('action'), form.serialize())
.done(function(data) {
// do something on success: perhaps show a "comment posted!" message.
})
.fail(function(xhr, status, error) {
// do something on failure: perhaps iterate through xhr.responseJSON and
// and insert the error messages into the form divs.
});


I'm trying to post a very simple comment with Ajax, when I'm not using Ajax the comment is posted and saved to the database just fine.


So far I've encountered 501 and 403 errors and all sorts of unwanted behaviour. I've tried to follow these instructions and I've read several answers on a similar topic on stackoverflow, but was unable to apply those solutions to my problem.


I'm really stuck here so any help would be greatly appreciated.


Relevant models.py:


class Photo(models.Model):
image = models.ImageField(
'image path', upload_to='images/%Y/%m/%d')
image_thumb = models.ImageField(
'thumbnail path', upload_to='images/thumbnails/%Y/%m/%d')
name = models.CharField(max_length=100)
description = models.CharField(max_length=150)
avg_rating = models.FloatField('average rating', default=5.1)

def __unicode__(self):
return self.description

class Comment(models.Model):
post_date = models.DateTimeField('posted')
comment_text = models.TextField(max_length=500)
photo = models.ForeignKey(Photo)

def __unicode__(self):
return self.comment_text

The comment form from forms.py:


class CommentForm(forms.Form):
comment_text = forms.CharField(widget=forms.Textarea)

And the view which normally handles comments in views.py:


def details(request, photo_id):
photo = get_object_or_404(Photo, pk=photo_id)
ratings_list = photo.rating_set.all().order_by('-id')

if request.method == 'POST':
form_c = CommentForm(request.POST)

if form_c.is_valid():
new_comment = Comment(
post_date = datetime.now(),
comment_text = form_c.cleaned_data['comment_text'],
photo = photo
)
new_comment.save()
if request.is_ajax():
return "???"
else:
return HttpResponseRedirect(reverse('photos:details', args= (photo_id,)))
else:
form_c = CommentForm()

return render(request, 'photos/details.html',
{'photo': photo, 'ratings_list': ratings_list[:5],
'form_c': form_c})

I've put question marks in there since by now I have no idea where should I redirect.


Relevant details.html template snippet:


<div id="commentSection">
{% for c in photo.comment_set.all %}
<p>On {{c.post_date|date:"dS \o\f F, \a\t H:i"}}, someone said: </p>
<p>{{c.comment_text}}</p>
<br>
{% endfor %}
</div>
<form id="commentForm" name="commentForm" action="{% url 'photos:details' photo.id %}" method="post">
{% csrf_token %}
<p>{{form_c.non_field_errors}}
{{form_c.comment_text.label_tag}}
{{form_c.comment_text.errors}}</p>
<p>{{form_c.comment_text}}</p>
<input type="submit" value="Post Comment" />
</form>

The urls.py:


from django.conf.urls import patterns, url
from photos import views

urlpatterns = patterns('',
url(r'^rate/(?P<photo_id>\d+)/$', views.rate, name='rate'),
url(r'^(?P<photo_id>\d+)/$', views.details, name='details'),
url(r'^$', views.index, name='index'),
)

I've added this script to avoid having the csrf validation fail when trying to submit comments via Ajax.


<script type="text/javascript">
$(document).ajaxSend(function(event, xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function sameOrigin(url) {
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
function safeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
});

And this is the Ajax part I've been struggling with today and yesterday:


$(document).ready(function() {
$('#commentForm').on('submit', function(e){
e.preventDefault();
var form = $(this);
$.ajax(
???
});
});
});

Thank you for your time.



You can't redirect from an Ajax post. In fact, the whole point of doing Ajax at all is to prevent the need for redirecting. You need to actually return some data: the usual way to do that is to return some JSON indicating what happens. If the form was valid and the save succeeded, you might just return an empty response: but if the form was not valid, you'll need to serialize the errors and return that as a JSON dict.


Then, in your Ajax script itself, you'll need to process that information and display it to the user. Your Ajax function should look something like:


var form = $(this);
$.post(form.attr('action'), form.serialize())
.done(function(data) {
// do something on success: perhaps show a "comment posted!" message.
})
.fail(function(xhr, status, error) {
// do something on failure: perhaps iterate through xhr.responseJSON and
// and insert the error messages into the form divs.
});