Django query using datetime flter - django

In my (Post) model I have
published = models.DateField(null=True)
My urls include the year/month/day eg
/post/category-1/2017/11/06/some-post/
which I am capturing through kwargs in my urls.py
In my view my query is
model = Post.objects.get(slug=kwargs['slug'],published__year=kwargs['year'],
published__month=kwargs['month'],published__day=kwargs['day'])
However, this is not working. The only date element which works is for year. I've read some posts here which talk about unsetting USE_TZ in settings.py which is obviously not a solution.
I have tried using a DateTime field as well, but that makes no difference.
Any help much appreciated.

Have a look at :
import datetime
sDate = '2017/11/06'
dtDate = datetime.datetime.strptime(sDate, "%Y/%m/%d")
models = Post.objects.filter(slug=kwargs['slug'],published=dtDate)
But this implies that you have the correct value in sDate. So as kristab requested pls post your url pattern

Related

Link column with a static text using django-tables2

I cannot find a replacement for the LinkColumn in the new versions of django-tables2. Author states that LinkColumn is deprecated and shouldn't be used. But the new linkify solution is poorly documented and doesn't have all the features of the old version. For example, I have this column:
edit = tables.LinkColumn(
'wagtailadmin_pages:edit', args=[A('page.pk')],
text='Edit'
)
It displays a link to the wagtail admin edit page called Edit. There's simply no way to achieve the same using linkify because linkify only works if you have valid accessor on the column. But accessor cannot return same static text for all rows (unless I modify the model to add a dummy property - but this particular model is in the 3rd party package and it would feel like a duct tape solution anyway).
In all other cases, column will not display a link. I've studied the source code and it seems that such case is simply not supported by the django-tables2 > 2.0.0.
Is there any clean and understandable way to construct a link column with a static link text using linkify?
Answering my own question. It seems that it is impossible to fully replace LinkColumn with the linkify feature. The following code solves my problem:
from django.urls import reverse
from django.utils.text import mark_safe
import django_tables2 as tables
from wagtail.core.models import PageRevision
class WagtailRevisionsTable(tables.Table):
title = tables.Column(
accessor='page.title',
linkify=lambda record: record.page.url,
verbose_name='Title'
)
edit = tables.Column(
accessor='page.pk'
)
class Meta:
model = PageRevision
fields = ('title', 'created_at', 'user', 'edit')
template_name = 'django_tables2/bootstrap-responsive.html'
def render_edit(self, value):
url = reverse('wagtailadmin_pages:edit', args=[value])
return mark_safe(f'Edit')
The code with the old LinkColumn was much more concise, I don't understand the reason for change and documentations really doesn't help. There's simply not enough information on linkify or render_col methods.
So I hope this answer will help some poor soul trying to port old code to the django-tables2 >= 2.0.

How can I convert the DateTimeField in Django from UTC to enduser's timezone (usually PST) when querying a Django model?

I'm querying a Django model connected to a table in my Postgres database that contains a datetime stored in UTC.
My query code looks something like this:
query_set = table_object.objects.values()
One of the columns in the query set is the datetime value in UTC.
The model looks like this:
class ops_inbox_view(models.Model):
requested_date = models.DateTimeField()
other_item = models.CharField(max_length=20)
other_item2 = models.CharField(max_length=40)
other_item3 = models.CharField(primary_key=True, max_length=10)
other_item4 = models.CharField(max_length=50)
other_item5 = models.CharField(max_length=50)
other_item6 = models.CharField(max_length=50)
I want to convert this into PST or robustly in the enduser's local time zone. My current solution is to use pandas with dt.tz_localize and dt.tz_convert after loading the query set into a dataframe but I'm trying to find a solution that is easily manageable in one location of the project file structure of the app. In my settings.py, I have TIME_ZONE set to 'US/Pacific' but because I'm using Pandas, the conversion to PST is not automatically done and will have to change many lines of code in my views.py to make the conversion with pandas.
Is there a way to not use Pandas and instead either make the field timezone aware or make the explicit conversion in the query code? Also looking for any other best practices in timezone management and display. Serving this datetimefield into an html file...
You can use F() with annotate
from datetime import timedelta
from django.db.models import DateTimeField, ExpressionWrapper, F
table_object.objects.annotate(modified_date=ExpressionWrapper(F('requested_date')+timedelta(minutes=960), output_field=DateTimeField())).filter(modified_date='2019-11-30')
Here you need to +/- minutes to convert utc datetime to your(PST) timezone and it will store converted dates into modofied_date, after that we can filter it.
Note:
You don't need to use pandas to convert timezones. Django good built-in timezone management tools.
Their timezone docs are quite good as well, so I'd suggest reading it all the way through.
The problem you're havingĀ seems very similar to one described in their docs

Change date format in Django admin page [duplicate]

I recently added a new model to my site, and I'm using an admin.py file to specify exactly how I want it to appear in the admin site. It works great, but I can't figure out how to get one of my date fields to include seconds in it's display format. I'm only seeing values like "Aug. 27, 2011, 12:12 p.m." when what I want to be seeing is "Aug. 27, 2011, 12:12*:37* p.m."
Try this in the ModelAdmin:
def time_seconds(self, obj):
return obj.timefield.strftime("%d %b %Y %H:%M:%S")
time_seconds.admin_order_field = 'timefield'
time_seconds.short_description = 'Precise Time'
list_display = ('id', 'time_seconds', )
Replacing "timefield" with the appropriate field in your model, of course, and adding any other needed fields in "list_display".
digging around I ended here but applied a different approach to my app.
Changing django admin default formats could be done changing the django locale formats for every type you want.
Put the following on your admin.py file (or settings.py) to change datetime default format at your django admin.
from django.conf.locale.es import formats as es_formats
es_formats.DATETIME_FORMAT = "d M Y H:i:s"
It will change the ModelAdmin's datetime formats on that file (or whole site if in settings).
It does not breaks admin datetime filters and order features as #Alan Illing has point out in comments .
hope this help in future
Extra info:
You can change it for every available locale in django, which are a lot.
You can change the following formats using this approach
from django.conf.locale.es import formats as es_formats
es_formats.DATETIME_FORMAT
es_formats.NUMBER_GROUPING
es_formats.DATETIME_INPUT_FORMATS
es_formats.SHORT_DATETIME_FORMAT
es_formats.DATE_FORMAT
es_formats.SHORT_DATE_FORMAT
es_formats.DATE_INPUT_FORMATS
es_formats.THOUSAND_SEPARATOR
es_formats.DECIMAL_SEPARATOR
es_formats.TIME_FORMAT
es_formats.FIRST_DAY_OF_WEEK
es_formats.YEAR_MONTH_FORMAT
es_formats.MONTH_DAY_FORMAT
If you've tried gabriel's answer but it did not work, try to set USE_L10N = False in settings.py, it works for me.
Note that if USE_L10N is set to True, then the locale-dictated format has higher precedence and will be applied instead
See: https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-DATETIME_FORMAT
The accepted answer is correct, however I found it a bit confusing to understand how/why it works. Below is a small example that I hope illustrates how to do this more clearly.
Django provides a few ways to display "custom" fields in your admin view. The way I prefer to achieve this behavior is to define a custom field in the ModelAdmin class and display that instead of your intended field:
from django.contrib import admin
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=50)
birthday = models.DateField()
class PersonAdmin(admin.ModelAdmin):
#admin.display(description='Birthday')
def admin_birthday(self, obj):
return obj.birthday.strftime('%Y-%m-%d')
list_display = ('name', 'admin_birthday')
Notice that instead of displaying the actual birthday field from the Person model, we define a custom field (admin_birthday) as a method in the PersonAdmin and display that instead by adding it to the list_display attribute. Furthermore, the admin.display() decorator modifies how Django will display this custom field in the admin view. Using this approach, the admin panel will show the NAME and BIRTHDAY fields but using your preferred date formatting for the date.
The reason I prefer this approach is you keep the Model field definitions separate from how you display them in the admin panel. You can read more about alternative approaches in the Django admin documentation.

Indexing Taggit tags with Algolia for Django: '_TaggableManager' object has no attribute 'name'

I'm having some issues using the Algolia Django integration with one of my models which contains a TaggitManager() field. I'm currently being thrown back the following error when running this command:
$ python manage.py algolia_reindex
AttributeError: '_TaggableManager' object has no attribute 'name'
I've had a look at the Taggit documentation, but I'm just not sure exactly how I would marry the method outlined with the Algolia search index method.
index.py:
import django
django.setup()
from algoliasearch_django import AlgoliaIndex
class BlogPostIndex(AlgoliaIndex):
fields = ('title')
settings = {'searchableAttributes': ['title']}
index_name = 'blog_post_index'
models.py:
from taggit.managers import TaggableManager
class Post(models.Model):
...some model fields...
tags = TaggableManager()
To index the taggit tags with your Post fields, you will need to expose a callable that returns a Blog Post's tags as a list of strings.
The best option is to store them as _tags, which will let you filter on tags at query time.
Your PostIndex would look like this:
class PostIndex(AlgoliaIndex):
fields = ('title', '_tags')
settings = {'searchableAttributes': ['title']}
index_name = 'Blog Posts Index'
should_index = 'is_published'
As for Post:
class Post(models.Model):
# ...some model fields...
tags = TaggableManager()
def _tags(self):
return [t.name for t in self.tags.all()]
Following these instructions, your records will be indexed with their respective tags:
You can check the taggit branch of our Django demo, which demonstrates these steps.
To answer my own question. I have now passed in both the model and the model index so Algolia now knows what to index and what not to index. Although I would like a method to allow Algolia to index taggit tags, alas, it is probably not possible.
My apps.py file:
import algoliasearch_django as algoliasearch
from django.apps import AppConfig
from .index import PostIndex
class BlogConfig(AppConfig):
name = 'blog'
def ready(self):
Post = self.get_model('Post')
algoliasearch.register(Post, PostIndex)
My index.py file:
from algoliasearch_django import AlgoliaIndex
class PostIndex(AlgoliaIndex):
fields = ('title')
settings = {'searchableAttributes': ['title']}
index_name = 'Blog Posts Index'
should_index = 'is_published'
And that should pretty much work! Simple when you know how, or after trying about 10 different options!
So since nobody is answering I tell you how I solved this issue but I have to say that it is not a nice Way and not a "clean" Solution at all. So what I did is went into "taggit managers" in the site-packages (env->lib->python2.x/3.x-> site_packages->taggit->managers.py) In the managers.py file you will find at line 394 this beautiful piece of code:
def __get__(self, instance, model):
if instance is not None and instance.pk is None:
raise ValueError("%s objects need to have a primary key value "
"before you can access their tags." % model.__name__)
manager = self.manager(
through=self.through,
model=model,
instance=instance,
prefetch_cache_name=self.name, # this is the line I comment out when building the index,
name=self.name #this is the line I added and needs to be commented out after the index is build.
)
return manager
So what I do when I want to rebuild the search index is comment out (putting"#" infront of the line) prefetch_cache_name=self.name, and replace it with name=self.name. So building the index will work. After the Index is finished building, you have to bring everything back as it was before (switch the "#" to name=self.name again and leave prefetch_cache_name=self.name, visible again).
As already mentioned this is probably not the best way but I had the same pain and this is working for me. It takes one minute when you have the routine. Since I have to rebuild the Index maybe once every two weeks, that isn't such a deal for me but if you have to do it very often this might be annoying...
Anyway I hope that helps you.
It can help you if you using django==2+
The problem is in get_queryset() method of TaggableManager
Open file with it (my path was: Pipenv(project_name)/lib/site-packages/taggit/manager.py)
Find _TaggableManager class and change method name get_queryset to get_query_set
Done. I wish taggit's developers will fixed this in future updates

Adding data to a Django model

This is something I have never really understood, so forgive me if it seems very basic. What is the correct/best way of adding data to a CharField model so that it is available in my DB? Should it be as choices below for this type of data?
I want to store the below URLs in my DB and make it possible to select one at random in my views.py
When I run the below code I get
URLS = 0
Should that not be 9?
models.py
class URLs(models.Model):
URL_CHOICES = (
('one', '/urlone/'),
('two', '/urltwo/'),
('three', '/urlthree/'),
('four', '/urlfour/'),
('five', '/urlfive/'),
('six', '/urlsix/'),
('seven', '/urlseven/'),
('eight', '/urleight/'),
('nine', '/urlnine/'),)
url = models.CharField(max_length=100, choices=URL_CHOICES)
def __unicode__(self):
return self
views.py
from survey.models import URLs
def begin(request):
surveyurls = URLs.objects.all().count()
print 'URLS = ', surveyurls
Thanks for any help.
The choices argument for a ModelField works differently than you seem to assume.
With choices, you can limit the accepted values for a model instance. It doesn't actually write anything into the database. To populate your database, you can use fixtures.
In the model you define how your data looks. Django will use this information to build your database structure.
If you want fill the database right from the start you should look at this: HowTo - Initial Data
the best way it's by the migration data file:
here's a example:
class Migration(migrations.Migration):
dependencies = [
('procesos', '0020_auto_20150703_1656'),
]
operations = [
migrations.RunSQL("UPDATE procesos_busquedainmueble SET tipo_inmueble_id=(filtros::json->>'tipo_inmueble')::int;"),