Filtering models with inheritance in Django - django

I have two Django model classes that are structured similar to the following:
class Build(models.Model):
project = models.CharField(max_length=100)
...
class CustomBuild(Build):
custom_type = ...
...
I want to select all Builds and CustomBuilds (each CustomBuild has a one-to-one relationship with a Build) from the database with a specific project attribute.
I believe Build.objects.filter(project="myproject") will select the correct objects but many of them will be missing the additional data (such as custom_type) that would be provided by a CustomBuild object. On the other hand, filtering CustomBuild.objects will exclude those objects that are not CustomBuilds.
How can I accomplish this? Thanks.

There are a couple approaches you can take to handling the QuerySets of "mixed models" that you obtain when you perform this kind of query. A lot of it depends on your ultimate goal.
The "simple and dumb" way, which I use a lot, is to manage the results with utility functions. If you plan to process the result of Build.objects.filter(project="myproject") in a template, for example, you could use custom template tags or filters to take special action. Assume in the below code build_objects contains the result of your filter():
{% for build in build_objects %}
{% if build|is_custom_build %}
<p>This is a custom build of custom type {{ build.custom_build.custom_type }}!</p>
{% endif %}
<p>This is a custom build OR a standard build</p>
{% endfor %}
The obvious problem here is if you have numerous subclasses, writing template filters may be impractical or grow tedious. However, in my experience I usually have a half-dozen subclasses at most so this is not always a problem.
You could also write a parameterized filter like so:
{% if build|is_of_buildtype:"custom_build" %}
With the filter code as follows:
def is_of_buildtype_filter(value, arg):
if hasattr(value, arg): return True
else: return False
This filter simply checks for the presence of the argument as an attribute on the build object (passed in as value). The argument string should be the name of the automatically generated OneToOneField that you want to detect, in this case custom_build.
For view code, similar sorts of helper functions would work the same way but are even easier because you don't need to write custom filters or tags.
This approach works in many cases, but there are more complicated scenarios where it might not be practical. Unfortunately, Django cannot natively provide you with a QuerySet that contains subclass instances when you perform operations on the base class (ie. a QuerySet that truly contains "mixed models"). You may require this in situations where processing the results with helper functions is not possible.
I personally avoid these situations entirely, usually by rethinking my model design. But if that's not possible, there are many interesting attempts at solutions, like this Inheritance MixIn. There are also several Django snippets on the subject. Be aware, though, that almost any solution like this will be performance-limited.

You can fetch Build objects with Build.objects.filter() and access the subclass when you need to:
qs = Build.objects.all()
build_obj = qs[4]
custom_build_obj = build_obj.custom_build
custom_build_obj.custom_type = ...

Related

How can one create a custom "as_table()" method for forms?

I have a relatively complicated form that's used in multiple places on my website (in fact, it's a form from which many other form classes inherit). In the templates, the inherited part of this form is always formatted identically—but that formatting is somehwat involved; each field is rendered and positioned manually in the template.
This means that every template which displays this form has a lot of identical HTML markup that renders the form appropriately.
I would like to create a custom output that can be called, similar to the as_table() methods. I'm aware that one can override the normal_row, error_row, etc. attributes—but the formatting of this form goes beyond that (for example, three of the form's five fields should be printed side-by-side, with a combined title). All of the tutorials/answered-questions I've seen either refer to overriding the above-mentioned attributes, or give instructions on how to manually render forms.
Originally, I was thinking something like this:
Class StrangeForm(form.Forms):
....
def as_table_custom():
html_string = "\
<tr><td>Title 1:</td><td>self.fields['field1']</td><tr>\
<tr><td>Title 2:</td><td>self.fields['field2']</td><tr>\
<tr><td>Titles 3, 4, 5:</td><td>self.fields['field3']\
</td><td>self.fields['field4']</td><td>self.fields['field5']</td></tr>\
"
return html_string
But, after reading through the _html_output() and as_table() methods of Django's forms.py file, it doesn't look like it'll be that easy. If I write this from scratch, have to somehow account for errors, help text, etc. I think.
Is there an easy way to override something such that the form's HTML output can be defined like above? Or do I have to re-write things from scratch. If the latter, how can I account for all of the things I need to account for?
I wouldn't take this approach. You're better off creating the form in an HTML template that you include in the various templates where you have a form you want to display that way.
So create a my_strange_form.html template where you assume a 'form' object is passed in the context with the right number of fields. In that template just create the HTML, using things like {{ field.label_tag }} and {{ field }}. You can loop through the fields with a {% for field in form %} and check the counter of your loop with {{ forloop.counter }}. I foresee a lot of {% if forloop.counter... %} statements to generate the combined row, and it will look ugly, but you'll only have to look at it once :-)
Then in your main templates {% include 'my_strange_form.html' with form=form %}.

Django: creating graphs in admin Inlines

I'm working in the admin interface, and I'm trying to create a InlineModelAdmin subclass that given a model will just give me certain values from related values (say, date and value fields) and use them in a subclassed template to build a graph.
Problem is: I don't know what to subclass in the inline!. The inline_admin_formset seems to have the form already cooked and I can't access the date. get_form I can't get to send the data I want to the template. I tried change_view to put the data as extra_context, but it's only called for the parent class. And so on.
Can anyone orient me as to where would be the best place to work?.
I know this would be a lot easier in a custom view, but the high command is adamant that this has to be done in the admin interface.
Thank you!
Looks like I managed to access the raw data from the inline objects using the following code in the template:
<script>
var data = google.visualization.arrayToDataTable([
["Date", "Value"],
{% for form in inline_admin_formset %}
["{{form.original.date}}", {{form.original.value}}],
{% endfor %}
]);
</script>
So it looks like now I only need to parameterize what fields the graph is going to plot from the inline, or from the object (date and value in this case). Perhaps add a graph_fields() method to both.
In any case, thanks to whoever gave this a thought.

Django's equivalence of ASP.NET UserControl

If anyone here is ASP.NET pro, you might know what I mean by user control. I wish to create a similar one in django instead.
So, my problem is that I have several pages in my website, but I need a search bar to appear in every pages. Since I require the views.py to operate this search bar, I cannot do a simple method of
{% include 'something.html' %}
Therefore, can anyone suggest how can I do it?
There are a couple of ways to accomplish what you're wanting to do:
Context Processors
Template Tags
Context Processors can augment the template context with values, regardless of which template is loaded. They are akin to filters in Rails.
Template Tags, like Context Processors, can accomplish anything you can do in Python, but are implemented at the template level.
If you need something to be present on every template, one of the simplest ways to accomplish this is with an inclusion tag, which can also accept values passed to it. An inclusion tag could be implemented at your highest level template, a.k.a your MasterPage, and as long as you don't put it in a block and override it, it would appear on every page that includes that template in its inheritance chain.
If it's just something you want to include on every page, and it doesn't need to do any processing, you should just be able to place the code you want in the top-most template and have subsequent templates inherit that.
I typically have a "base.html" template that all of my templates inherit from. If I need something to be in every page, I put it there. If it's something I want there by default, but want to be able to augment it in subsequent templates, I will place it into a block. That block will let you include or override its default content.
I know this post is kind of old but I just came across it and found a kind-of-solution that works. I call it kind-of-solution because it is a workaround.
I have a few different sites on which I want to display logging information. This display always looks the same (it has the same html) and has the same database table and model class behind it.
My solution/workaround uses the django filters:
in views.py I put the list of log-entries in the context
context = {'list_log': Log.objects.filter(condition = True) }
template = loader.get_template('my_html_file.html')
return HttpResponse(template.render(context, request))
in my_html_file.html I use a custom filter
{{ list_log|get_log_uc|safe }}
in the filters.py I load another html file with this custom filter
#register.filter
def get_log_uc(list_log):
template = loader.get_template('user_control_log.html')
context = { 'list_log' : log }
return template.render(context)
in user_control_log.html I have the user control equivalent html
{% for log in list_log %}
<p>log.something</p>
{% endfor %

Database localization in Django

I am using .mo files for localization in Django.
Also, in my database, I store some translated text in different fields, such as:
name_en, name_es, name_de (they are all columns in each row).
What will be the best method to choose the correct field inside a template?
i.e.:
{{ name.some_method }} will generate the correct translation based on the current localization.
Thanks,
Meit
You should look at http://goodcode.io/articles/django-multilanguage/ Here’s a simple solution that may fit your use case and is easy to implement and understand.
You should look at Django Transmeta, it work the same way as what you've done (DB fields with language code) but it's a more complete solution. It already deal with the template stuff, etc.
You can check Model Internationalization and Django Packages for more info and ideas in this domain.
I can see two method for doing this, one in your view and the other one is in the template...
In view:
Probably you keep the user language information somewhere so,
user_lang = 'es'
obj = Somemodel.objects.get(pk=123434)
obj.local_name = getattr(obj, 'name_%s'%user_lang)
So, you keep local translation in a specific variable of the instance and in your template you can use is as:
{{obj.local_name}}
But that might be costly if you wish to pass the template a queryset instead of a single instance. For a such usege you have to evaluate that value for each object in your queryset.
In template:
That is a more complex way of solving the porblem in the template...
Define a template tag and pass object_id, and local language information and get the translated text using a similar getattr function. But in that point, if you wish to use this for more than one model, you probably have to pass a content type information for your template tag too, such as:
{% get_translation <object_id> <content_type_id> <local_language> %}
And in your template tag function, do something like:
from django.contrib.contenttypes.models import ContentType
....
cont_obj = Content_type.objects.get_for_id(<cotent_type_id>) #get the related model
obj = cont_obj.get_object_for_this_type(pk=<object_id>) # get your object
return getattr(obj, 'name_%s'%<local_language>)

Django tags and filters in Lift?

This is a generalization of my previous question about pluralize filter:
Does lift have an equivalent of Django's tags and filters?
Tags are small piece of predefined code that can be used directly in html template, for example:
{% now "jS F Y H:i" %}
renders the time right now in the given format.
Filters
Filters operate (in html template) on the context variables in the template, for example:
{{ value|capfirst }}
if called on a value "john" will result in "John". Or:
{{ value|length }}
will render the length of the string into the template.
As you can see the filters operate on the context variables that are passed to the template.
Considering tags, you could define those yourself with snippets.
As snippet is basically a callback much as a Django tag is. You don’t get any easier syntax, though, because Lift’s templates are pure XML/Html.
<Lift:Tag.now format="jS F Y H:i" />
And the logic would be defined in
class Tag {
def now: NodeSeq = // ...
}
Filtering is something you generally can’t do in a Lift template because Lift doesn’t allow any variables in a template. The whole concept is thus inapplicable. (You could do XML transforms or or bind magic but that would be a bit too much for a simple value.length.)
No, if you need the length of some value in your Html, you will have to define that inside the snippet and expose it.
If you really can’t live without filters in your template (though I can assure you, it is a good thing to separate all HTML template and code and it works once you are used to it), have a look at Scalate which may be used together with Lift as well.
This kind of logic should be in the render method of a snippet. Display code in pure Scala (rather than in a template language hybrid) is a first-class citizen with respect to testing, IDE's and refactoring tools.
These kinds of transforms don't come built-in, but you can add them with implicits:
class HappyString(s: String) {
def capfirst = ....
}
implicit def toHappyString(s: String) = new HappyString(s)
Then call these in your render method before binding whatever value it is you're generating.