Class has no 'objects' member in django - python

from django.http import HttpResponse
from .models import Destination
def index(request):
boards = Destination.objects.all()
boards_names = list()
for Destination in boards:
boards_names.append(Destination.destinationtext)
response_html = '<br>'.join(boards_names)
return HttpResponse(response_html)
I have written this code following just for practice of django framework but I am getting the following errors through pylint :
E1101:Class 'Destination' has no 'objects' member
E0601:Using variable 'Destination' before assignment

You have two different issues, and not just one as you say:
E1101:Class 'Destination' has no 'objects' member: Is a warning
that occurs because pylint doesn't know about our special Django variables. A pylint plugin like pylint-django might do the trick.
E0601:Using variable 'Destination' before assignment: In the for loop in your code you defined a variable called Destination. This is not only bad practice because python variables need to be in lowercase_underscore but it overrides the Destination class, and that's what is causing this error. You probably wanted to do something like this:
for d in boards:
# Or:
for destination in boards:

You wrote in your view:
for Destination in boards:
# ...
This means that Python sees Destination as a local variable, a local variable that you use before it is assigned.
You can rename the variable in the loop to solve the problem, but actually you can make it more elegant and faster here by using .values_list(..):
from django.http import HttpResponse
from .models import Destination
def index(request):
response_html = '<br>'.join(
Destination.objects.values_list('destinationtext', flat=True)
)
return HttpResponse(response_html)
Nevertheless, I'm still not convinced that this solves the matter, since the destinationtext could contain HTML, which then will mix up in the response. Usually it is better to use templates.

Related

access variable value from view within a django class

I currently have a class urldata.py, with a loop:
from Scanner.views import Processinitialscan
for element in elements:
dbInsert = PathsOfDomain(pathToScan=element.attrs["href"],FKtoTld=Processinitialscan.)
dbInsert.save()
I have a view.py with a variable EnteredDomainRowID, that I want to use in the class above:
def Processinitialscan(request):
EnteredDomainRowID = GetEnteredDomainObjects.pk
I've been trying:
FKtoTld=Processinitialscan.EnteredDomainRowID
in :
dbInsert = PathsOfDomain(pathToScan=element.attrs["href"],FKtoTld=Processinitialscan.)
but, this doesn't seem to work.
My question, how do I access the value from the variable EnteredDomainRowID from views.py within my class urldata.py for the variable dbInsert (as shown above) ?
Additionally, I cannot seem to be able to import views.py into a urldata.py , is this not possible?
Any help is really, really appreciated.
Thank you.
Unfortunately, that's not the way python works EnteredDomainRowID is not a property of your function object, but it is a local variable to the function.
You could pretty easily convert this to a class based view, which will allow you to easily access the classes attributes.

Django: Is separating views.py into its own module a good idea?

Dilemma
My views.py gets pretty unwieldy, so I want to separate it into a separate views module inside of my app. However, I'm not sure this is a good idea, for two reasons:
If my views file is the same name as the app name, I cannot import the model without using django.db.get_model, therefore I am worried my approach may be flawed. I have heard it is best practice to avoid name collision within modules; should I rename my view files?
I'm not sure if creating a views module is considered good practice within the Django community in general.
Example
For example, for an app named blogs, with a Blog model and a Post model:
blogs/
__init__.py
models.py
urls.py
views/
__init__.py
blogs.py
posts.py
Here is my blogs.views.blogs:
# project/blogs/views/blogs.py
from django.db.models import get_model
from django.shortcuts import get_object_or_404
from django.views.generic import ListView, DetailView
# Cannot import model directly, results in `ImportError: No module named models`.
# This can be resolved if I resolve the name collision between this file and
# the app itself.
#
# from blogs.models import Blog
class BlogListView(ListView):
model = get_model('blogs', 'Blog')
def get_queryset(self):
return self.model.objects.all()
class BlogDetailView(DetailView):
model = get_model('blogs', 'Blog')
def get_object(self):
blog_pk = self.kwargs.get('blog_pk')
return get_object_or_404(self.model.objects, pk=blog_pk)
Question
My question is twofold:
Should I be separating my views in the first place?
If so, is using get_model a good idea, or is there a way I can import my model directly without using this method? Or should I change my view file names, for example by adding the suffix _views (e.g.: blogs.views.blogs_views.py) in order to avoid the problem altogether?
I cannot import the model without using django.db.get_model
You can: from project_name.app_name.models import MyModel And it's preferable way, 'relative imports for intra-package imports are highly discouraged', - as said in PEP-8.
There shouldn't be any problems with names, views.py has no special meaning in Django, it's just a convention.
You can keep your views in any file in any module under any name you want. So there is no special rules here, if you think that separating the module into submodules will be good, do it.
As DrTyrsa points out, views has no special meaning. So as an alternative to creating a subpackage, you could just create several files at the same level as the existing views.py - blog_views.py, posts_views.py, etc. As long as you use the correct reference in urls.py, this works fine.

Python : Singleton class object to persist list between imports ? (Like django admin register)

I want to have dict / list to which I can add values, just like models can be added to the admin register in django !
My attempt : (package -> __init__.py)
# Singleton object
# __init__.py (Package: pack)
class remember:
a = []
def add(data):
a.append[data]
def get():
return a
obj = remember()
# models1.py
import pack
pack.obj.add("data")
# models2.py
import pack
pack.obj.add("data2")
print pack.obj.get()
# We should get: ["data", "data2"]
# We get : ["data2"]
How to achieve the desired functionality ?
Some say that methods can do this if you don't need sub-classing, how to do this with methods ?
Update:
To be more clear :
Just like django admin register any one can import and register itself with admin, so that register is persisted between imports.
If it's a singleton you're after, have a look at this old blog post. It contains a link to a well documented implementation (here).
Don't. If you think you need a global you don't and you should reevaluate how you are approaching the problem because 99% of the time you're doing it wrong.
If you have a really good reason to do it perhaps thread_locals() will really solve the problem you're trying to solve. This allows you to set up thread level global data. Note: This is only slightly better than a true global and should in general be avoided, and it can cause you a lot of headaches.
If you're looking for a cross request "global" then you most likely want to look into storing values in memcached.

Call method dynamically if it exists in Django

I'm creating website based on Django (I know it's pure Python, so maybe it could be also answered by people who knows Python well) and I need to call some methods dynamically.
For example I have few applications (modules) in my website with the method "do_search()" in the views.py. Then I have one module called for example "search" and there I want to have an action which will be able to call all the existing "do_search()" in other applications. Of course I don't like to add each application to the import, then call it directly. I need some better way to do it dynamically.
I can read INSTALLED_APPS variable from settings and somehow run through all of the installed apps and look for the specific method? Piece of code will help here a lot :)
Thanks in advance!
Ignas
I'm not sure if I truly understand the question, but please clarify in a comment to my answer if I'm off.
# search.py
searchables = []
def search(search_string):
return [s.do_search(search_string) for s in searchables]
def register_search_engine(searchable):
if hasattr(searchable, 'do_search'):
# you want to see if this is callable also
searchables.append(searchable)
else:
# raise some error perhaps
# views.py
def do_search(search_string):
# search somehow, and return result
# models.py
# you need to ensure this method runs before any attempt at searching can begin
# like in models.py if this app is within installed_apps. the reason being that
# this module may not have been imported before the call to search.
import search
from views import do_search
search.register_search_engine(do_search)
As for where to register your search engine, there is some sort of helpful documentation in the signals docs for django which relates to this.
You can put signal handling and registration code anywhere you like. However, you'll need to make sure that the module it's in gets imported early on so that the signal handling gets registered before any signals need to be sent. This makes your app's models.py a good place to put registration of signal handlers.
So your models.py file should be a good place to register your search engine.
Alternative answer that I just thought of:
In your settings.py, you can have a setting that declares all your search functions. Like so:
# settings.py
SEARCH_ENGINES = ('app1.views.do_search', 'app2.views.do_search')
# search.py
from django.conf import settings
from django.utils import importlib
def search(search_string):
search_results = []
for engine in settings.SEARCH_ENGINES
i = engine.rfind('.')
module, attr = engine[:i], engine[i+1:]
mod = importlib.import_module(module)
do_search = getattr(mod, attr)
search_results.append(do_search(search_string))
return search_results
This works somewhat similar to registering MIDDLEWARE_CLASSES and TEMPLATE_CONTEXT_PROCESSORS. The above is all untested code, but if you look around the django source, you should be able to flesh this out and remove any errors.
If you can import the other applications through
import other_app
then it should be possible to perform
method = getattr(other_app, 'do_' + method_name)
result = method()
However your approach is questionable.

Manager isn't accessible via model instances

I'm trying to get model objects instance in another one and I raise this error :
Manager isn't accessible via topic instance
Here's my model :
class forum(models.Model):
# Some attributs
class topic(models.Model):
# Some attributs
class post(models.Model):
# Some attributs
def delete(self):
forum = self.topic.forum
super(post, self).delete()
forum.topic_count = topic.objects.filter(forum = forum).count()
Here's my view :
def test(request, post_id):
post = topic.objects.get(id = int(topic_id))
post.delete()
And I get :
post.delete()
forum.topic_count = topic.objects.filter(forum = forum).count()
Manager isn't accessible via topic instances
The error in question is caused when you try to access the Manager of a model through an instance of the model. You have used lower case class names. This makes it hard to say if the error is caused by an instance accessing the Manager or not. Since other scenarios that can cause this error are unknown I am proceeding on the assumption that you have somehow mixed up the topic variable so that you end up pointing to an instance of the topic model instead of the class.
This line is the culprit:
forum.topic_count = topic.objects.filter(forum = forum).count()
# ^^^^^
You have to use:
forum.topic_count = Topic.objects.filter(forum = forum).count()
# ^^^^^
# Model, not instance.
What is going wrong? objects is a Manager available at the class level, not to the instances. See the documentation for retrieving objects for details. Money quote:
Managers are accessible only via model classes, rather than from model instances, to enforce a separation between "table-level" operations and "record-level" operations.
(Emphasis added)
Update
See the comments from #Daniel below. It is a good idea (nay, you MUST :P) to use title case for class names. For instance Topic instead of topic. Your class names cause some confusion whether you are referring to an instance or a class. Since the Manager isn't accessible via <model> instances is very specific I am able to offer a solution.The error may not be so self evident always.
topic.__class__.objects.get(id=topic_id)
For django < 1.10
topic._default_manager.get(id=topic_id)
Though you should not use it like this. The _default_manager and _base_manager are private, so it's recomended to use them only if you're inside the Topic model, like when you want to use the Manager in a proprietary function let's say:
class Topic(Model):
.
.
.
def related(self)
"Returns the topics with similar starting names"
return self._default_manager.filter(name__startswith=self.name)
topic.related() #topic 'Milan wins' is related to:
# ['Milan wins','Milan wins championship', 'Milan wins by one goal', ...]
Could also be caused by a pair of parantheses too much, e.g.
ModelClass().objects.filter(...)
instead of the correct
ModelClass.objects.filter(...)
Happens to me sometimes when bpython (or an IDE) automatically adds parantheses.
The result, of course, is the same - you have an instance instead of a class.
if topic were a ContentType instance (which it is not), this would have worked:
topic.model_class().objects.filter(forum = forum)
I just had an issue similar to this error. And looking back at your code it seems that it could be your issue too. I think your issue is that your comparing "id" to "int(topic_id)" and topic_id is not set.
def test(request, post_id):
post = topic.objects.get(id = int(topic_id))
post.delete()
I'm guessing your code should use "post_id" not "topic_id"
def test(request, post_id):
post = topic.objects.get(id = int(post_id))
post.delete()
I got the same error below:
AttributeError: Manager isn't accessible via CustomUser instances
When I accessed Manager with request.user.objects as shown below:
"views.py"
from django.http import HttpResponse
def test(request):
print(request.user.objects)
return HttpResponse("Test")

Categories