Django Model DateField and input fixture - django

Model file includes :
class Foo(models.Model):
bar = models.DateTimeField()
Fixture file.json includes:
{
"model": "app.Foo",
"pk": "1",
"fields": {
"bar": "2018/4/20",
}
},
when I'm trying to add fixtures with "python manage.py loaddata" result is:
django.core.serializers.base.DeserializationError: Problem installing fixture
'C:\Projects\TestProject\app\fixtures\file.json': ['“2018/4/20” value has an
invalid format. It must be in Y
YYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] format.']: (app.Foo:pk=1) field_value was '2018/4/20'
so my question is how can I add date format with "YYYY/MM/DD" to my Model files ?

your using DateTimeField() and your getting data is only date that's why it's getting the error instead of DateTimeField() use DateField()
for example:class Foo(models.Model):
bar = models.DateField()

The Django models.DateField and models.DateTimeField expect input either as python datetime objects or in ISO format (with "-" separators, not "/" separators). This is not something you can easily change because it is also what is used to save the values in the database. So what you want isn't possible.
The only option I see is that you write your own management command that first parses your json fixture, changing the dates format to ISO and saving to a new file, then calling the loaddata command from within your own handle() method.
Note: The corresponding form fields, forms.DateField, are flexible and accept various input formats and allow you to specify which input format you want to use. In fact, if you enable i18n then they will accept international input formats like 2020/03/12. But that doesn't really help you with loaddata which doesn't use a form at all.

Related

Storing a .html report with a data model

I am new to Django, and I am looking for the best approach to the following problem.
I have an application that is producing two reports. One is a JSON blob so I store it in psql with data model that uses JSONField.
The second report is a .html file.
The .html file will be generated multiple times a day so the first thing that came to mind was storing it in the db.
I need to be able to pull the report as well so it can be displayed to the user in the UI.
I created a test data model using TextField:
class TestResultsHTML(models.Model):
name = models.CharField(max_length=200)
report = models.TextField()
It makes it into the Db no problem, however when I attempt to retrieve it I can't seem to get the actual report:
In [3]: html_results = TestResultsHTML.objects.get(id=4)
In [4]: html_results.name
Out[4]: 'b0f5c336-867a-44a3-a5ef-6297bf6042cf'
In [5]: html_results.report
Out[5]: "<_io.TextIOWrapper name='report.html' mode='r' encoding='UTF-8'>"
I was expected that .report would return the actual contents of the file. The file itself is 1800+ lines.
Is this a good approach or is this not the intended use of TextField?
A TextField doesn't store the file, Django has a FileField for this (see here). This saves the file to a certain location/folder and the object saved in the DB essentially stores that location which you can then access later. Something like this:
class TestResultsHTML(models.Model):
name = models.CharField(max_length=200)
file_loc = models.FileField(upload_to=upload_location)
Then open the file at a later date with something like this:
with open(html_results.file_loc, 'w'):

Converting JSON to model instance in Django

What's the best way in django to update a model instance given a json representation of that model instance.
Is using deserialize the correct approach? Are there tutorials available out there?
The best approach would be to utilize one of the existing Django applications that support serializing model instances to and from JSON.
In either case, if you parse the JSON object to a Python dictionary, you can basically use the QuerySet.update() method directly.
So, say you get a dictionary where all the keys map to model attributes and they represent the values you'd want to update, you could do this:
updates = { # Our parsed JSON data
'pk': 1337,
'foo': 'bar',
'baz': 192.05
}
id = updates.pop('pk') # Extract the instance's ID
Foo.objects.filter(id=id).update(**updates) # Update the instance's data

"T" character added to serialized date with Django wadofstuff serializer

I recently upgraded to Django 1.4 from 1.1. I have been running WadofStuff Django Serializers 1.0.0. After upgrade, I noticed that dates from my django model get serialized with a 'T' character inserted:
{"pk": 7, "model": "ao.message", "fields": {"content_file": "bar.wav", "date": "2012-07-04T10:58:46", "summary_file": "foo.wav"}}
What's up with that 'T'? Can/should it be removed? Is there a way to specify my desired output date format to the serializer (say, if I didn't want it to return with a 'T')?
Thanks
A single point in time can be represented by concatenating: a complete date expression, the letter T as a delimiter, and a valid time expression. For example "2007-04-05T14:30" (Wikipedia Link )
For further details regarding this T insertion in datetime format as far as python is concerned, you may go to this link: "Python Datetime Representations". The first example specifically illustrates your problem and suggests its solutions too.

how to write a query to get find value in a json field in django

I have a json field in my database which is like
jsonfield = {'username':'chingo','reputation':'5'}
how can i write a query so that i can find if a user name exists. something like
username = 'chingo'
query = User.objects.get(jsonfield['username']=username)
I know the above query is a wrong but I wanted to know if there is a way to access it?
If you are using the django-jsonfield package, then this is simple. Say you have a model like this:
from jsonfield import JSONField
class User(models.Model):
jsonfield = JSONField()
Then to search for records with a specific username, you can just do this:
User.objects.get(jsonfield__contains={'username':username})
Since Django 1.9, you have been able to use PostgreSQL's native JSONField. This makes search JSON very simple. In your example, this query would work:
User.objects.get(jsonfield__username='chingo')
If you have an older version of Django, or you are using the Django JSONField library for compatibility with MySQL or something similar, you can still perform your query.
In the latter situation, jsonfield will be stored as a text field and mapped to a dict when brought into Django. In the database, your data will be stored like this
{"username":"chingo","reputation":"5"}
Therefore, you can simply search the text. Your query in this siutation would be:
User.objects.get(jsonfield__contains='"username":"chingo"')
2019: As #freethebees points out it's now as simple as:
User.objects.get(jsonfield__username='chingo')
But as the doc examples mention you can query deeply, and if the json is an array you can use an integer to index it:
https://docs.djangoproject.com/en/2.2/ref/contrib/postgres/fields/#querying-jsonfield
>>> Dog.objects.create(name='Rufus', data={
... 'breed': 'labrador',
... 'owner': {
... 'name': 'Bob',
... 'other_pets': [{
... 'name': 'Fishy',
... }],
... },
... })
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': None})
>>> Dog.objects.filter(data__breed='collie')
<QuerySet [<Dog: Meg>]>
>>> Dog.objects.filter(data__owner__name='Bob')
<QuerySet [<Dog: Rufus>]>
>>> Dog.objects.filter(data__owner__other_pets__0__name='Fishy')
<QuerySet [<Dog: Rufus>]>
Although this is for postgres, I believe it works the same in other DBs like MySQL
Postgres: https://docs.djangoproject.com/en/2.2/ref/contrib/postgres/fields/#querying-jsonfield
MySQL: https://django-mysql.readthedocs.io/en/latest/model_fields/json_field.html#querying-jsonfield
This usage is somewhat anti-pattern. Also, its implementation is not going to have regular performance, and perhaps is error-prone.
Normally don't use jsonfield when you need to look up through fields. Use the way the RDBMS provides or MongoDB(which internally operates on faster BSON), as Daniel pointed out.
Due to the deterministic of JSON format,
you could achieve it by using contains (regex has issue when dealing w/ multiple '\' and even slower), I don't think it's good to use username in this way, so use name instead:
def make_cond(name, value):
from django.utils import simplejson
cond = simplejson.dumps({name:value})[1:-1] # remove '{' and '}'
return ' ' + cond # avoid '\"'
User.objects.get(jsonfield__contains=make_cond(name, value))
It works as long as
the jsonfield using the same dump utility (the simplejson here)
name and value are not too special (I don't know any egde-case so far, maybe someone could point it out)
your jsonfield data is not corrupt (unlikely though)
Actually I'm working on a editable jsonfield and thinking about whether to support such operations. The negative proof is as said above, it feels like some black-magic, well.
If you use PostgreSQL you can use raw sql to solve problem.
username = 'chingo'
SQL_QUERY = "SELECT true FROM you_table WHERE jsonfield::json->>'username' = '%s'"
User.objects.extra(where=[SQL_EXCLUDE % username]).get()
where you_table is name of table in your database.
Any methods when you work with JSON like with plain text - looking like very bad way.
So, also I think that you need a better schema of database.
Here is the way I have found out that will solve your problem:
search_filter = '"username":{0}'.format(username)
query = User.objects.get(jsonfield__contains=search_filter)
Hope this helps.
You can't do that. Use normal database fields for structured data, not JSON blobs.
If you need to search on JSON data, consider using a noSQL database like MongoDB.

TimeField format in Django template

I'm writing an application in Django and using several TimeFields in a model. I only want to work with the time format hh:mm (not hh:mm:ss or hh p.m./a.m. or other things).
I have set the django setting TIME_FORMAT = 'H:i' and USE_L10N = False according to the documentation,
USE_L10N overrides TIME_FORMAT if set to True
In my template I'm using input boxes automatically created by Django like:
{{formName.timeField}}
The problem is that as long as I introduce something like "10:00" and do a POST, when the POST is done Django (or whatever) turns it into "10:00:00" (so it adds the seconds).
Is there a way to specify the format in which datetime fields display saved dates? If I could just use something like |date:"H:i" in the value of the input box that would do the trick.
On the other side I know I could do the input box manually (not directly using {{formName.timeField}}), but I've had some problems in the past with that so I would like to avoid that (at least for the moment).
There is also this similar question in Django TimeField Model without seconds, but the solution does not work (it gives me 'NoneType' object has no attribute 'strptime')
I had exactly this problem in my app, and solved it by passing a format parameter to Django's TimeInput widget:
from django import forms
class SettingsForm(forms.Form):
delivery_time = forms.TimeField(widget=forms.TimeInput(format='%H:%M'))
Assuming you have a format you want all TimeFields to use, you can add the TIME_INPUT_FORMATS to your settings file. For example, TIME_INPUT_FORMATS = ('%I:%M %p',) will format your times as "5:30 PM".
The docs: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TIME_INPUT_FORMATS