I have the following structure scenario in my models.py :
from django.db import models
class SensorManager(models.Manager):
def create_sensor(self,numero,pinoFisico):
sensor = self.create(numero = numero,
pinoFisico = pinoFisico,
ativo = False)
return sensor
class Sensor(models.Model):
numero = models.IntegerField()
pinoFisico = models.IntegerField()
ativo = models.BooleanField()
dataUltimoReconhecimento = models.DateTimeField()
situacao = None
moduloSensor = None
#Manager
objects = SensorManager()
def __init__(self):
self.moduloSensor = ModuloSensor()
and, in views.py file, i have this:
def formSensores(request):
sensores = Sensor.objects.all()
print sensores
return render(request,"speedapp/monitoraSensores.html",{"sensores": sensores})
When I try to use objects in
print sensores
i get the following stack:
[17/Apr/2017 00:38:09] "GET /speedapp/ HTTP/1.1" 200 3649
Internal Server Error: /speedapp/sensores/
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/pi/Documents/speed_project/speed/speedapp/views.py", line 39, in formSensores
print sensores
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 234, in __repr__
data = list(self[:REPR_OUTPUT_SIZE + 1])
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 258, in __iter__
self._fetch_all()
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 1074, in _fetch_all
self._result_cache = list(self.iterator())
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 69, in __iter__
obj = model_cls.from_db(db, init_list, row[model_fields_start:model_fields_end])
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 460, in from_db
new = cls(*values)
TypeError: __init__() takes exactly 1 argument (6 given)
[17/Apr/2017 00:38:11] "GET /speedapp/sensores/ HTTP/1.1" 500 15557
As the stack, it seems to be a problem at the moment of building the Sensor object by the SensorManager method in the __init__() method in class from_db, where N arguments were expected ... this problem is related to the my Custom Manager SensorManager?
P.S:
This error does not happens for other objects that are also used with the "all()" method through models.Manager, only for this Sensor class
Only happen when i try "use" instance of list objects, get with all() method, for example: print the value of it
I found this and this related questions in my search, But I could not solve my problem with them
So here's the high level answer. The problem is that you were overriding the __init__ method on the model. You really, really should try to avoid that. Here's some documentation on other options; read the big green note: https://docs.djangoproject.com/en/1.11/ref/models/instances/#django.db.models.Model
Here's an excerpt:
You may be tempted to customize the model by overriding the __init__ method...Rather than overriding __init__, try using one of these approaches
1. Add a classmethod on the model class
2. Add a method on a custom manager (usually preferred)
If you absolutely need to override __init__, then don't forget to call super() pass the values down, and let Django do its stuff first.
Related
Thank you so much for your help, i really appreciate it.
I get this error "'tuple' object has no attribute 'user'"
Anybody can tell me if my codes is right.
im trying to make artist followers system.
View.py
#api_view(['GET'])
#permission_classes([IsAuthenticated])
def artist_follow(request, pk):
artist = Artist.objects.get(pk=pk)
current_user = User.objects.get(pk=request.user.id)
# check the current user already followed the artsit, if exist remove it else add
if artist.followers().user.filter(user=current_user).exists(): # This line throw error
artist.followers().user.remove(current_user)
else:
artist.followers().user.add(current_user)
return Response(status=status.HTTP_200_OK)
Model.py
class Artist(models.Model):
name = models.CharField(unique=True, max_length=100)
.....
def __str__(self):
return self.name
def followers(self):
return ArtistFollower.objects.get_or_create(artist=self)
class ArtistFollower(models.Model):
artist = models.OneToOneField(Artist, on_delete=models.CASCADE)
user = models.ManyToManyField(User, related_name='user_artist_followed')
def __str__(self):
return self.artist.name
Traceback
Traceback (most recent call last):
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/rest_framework/decorators.py", line 50, in handler
return func(*args, **kwargs)
File "/Users/username/Desktop/Clients/app/source/app/artists/web/views.py", line 44, in artist_follow
if artist.followers().user.filter(user=current_user).exists():
Exception Type: AttributeError at /api/v1/web/artists/1/follow
Exception Value: 'tuple' object has no attribute 'user'
Your .followers() method uses .get_or_create(…) [Django-doc], and thus:
Returns a tuple of (object, created), where object is the retrieved or created object and created is a boolean specifying
whether a new object was created.
You can return the item that is obtained or constructed by subscripting:
class Artist(models.Model):
# …
def followers(self):
return ArtistFollower.objects.get_or_create(artist=self)[0]
or work with a throw away variable:
class Artist(models.Model):
# …
def followers(self):
obj, __ = ArtistFollower.objects.get_or_create(artist=self)
return obj
It however does not seem to make much sense to create a ArtistFollower model. Why not create a ManyToManyField to the User class in Artist model. This will simplify the modeling, and reduce the size of the database.
Such model thus looks like:
from django.conf import settings
class Artist(models.Model):
name = models.CharField(unique=True, max_length=100)
followers = models.ManyToManyField(
settings.AUTH_USER_MODEL,
related_name='following_artists'
)
You thus can then access the followers of an artist with:
my_artist.followers.all() # queryset of User objects
or for a user the artists they are following with:
my_user.following_artists.all()
You can also edit the ManyToManyField at both directions. For more information, see te section on many-to-many relations of the documentation.
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
I'm trying to make a multi-choice rest api with Django REST framework and django-multiselectfield.
Currently inside the model I have:
ANIMAL = (
('dog', 'Dog'),
('cat', 'Cat'),
)
class MyForm(models.Model):
...
animals = MultiSelectField(choices=ANIMAL)
and in my serializer I have:
class MyFormSerializer(serializers.ModelSerializer):
class Meta:
model = MyForm
fields = (..., 'animals')
animals = fields.MultipleChoiceField(choices=ANIMAL)
When I'm trying to POST into the api using this kind of body:
{
...
"animals": ["cat"],
...
}
I get an error: TypeError: Object of type 'set' is not JSON serializable
Traceback (most recent call last):
File "C:\Python36\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Python36\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Python36\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Python36\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "c:\mysite\myserver\myform\views.py", line 15, in angels_add
return JsonResponse(serializer.data, status=201)
File "C:\Python36\lib\site-packages\django\http\response.py", line 558, in __init__
data = json.dumps(data, cls=encoder, **json_dumps_params)
File "C:\Python36\lib\json\__init__.py", line 238, in dumps
**kw).encode(obj)
File "C:\Python36\lib\json\encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "C:\Python36\lib\json\encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File "C:\Python36\lib\site-packages\django\core\serializers\json.py", line 104, in default
return super().default(o)
File "C:\Python36\lib\json\encoder.py", line 180, in default
o.__class__.__name__)
TypeError: Object of type 'set' is not JSON serializable
Though, the form is submitted and I can see the entire data in the admin panel succesfully (?).
I'm using the following versions:
Django==2.2.1
djangorestframework==3.9.3
django-multiselectfield==0.1.8
any idea why I get this exception?
also, I can switch from multiselectfield to another technology if something else would work and will allow me to add multiple choice fields which I can filter later from the admin panel
class MyFormAdmin(admin.ModelAdmin):
list_filter = (
'animals',
...
)
I've read about ArrayField, but I'm not happy with a solution that fit only one kind of db (postgres) as I might use another.
Thanks in advance,
Etay.
From the source code, the to_representation() method of MultipleChoiceField returns data as set
Create a custom MultipleChoiceField class and use it in your serializer
class CustomMultipleChoiceField(fields.MultipleChoiceField):
def to_representation(self, value):
return list(super().to_representation(value))
class MyFormSerializer(serializers.ModelSerializer):
class Meta:
model = MyForm
fields = (..., 'animals')
animals = CustomMultipleChoiceField(choices=ANIMAL)
JPG's solution might work in some cases, but is not really rugged. (also depends on your use case)
A more low level way of solving this, is by extending the JSONEncoder or even better DjangoJSONEncoder (which is already extended) and using it. This way, you only have to implement it ones.
class CustomJSONEncoder(DjangoJSONEncoder):
"""
Custom encoder that also supports `set`, since we require this for
saving the `MultipleChoiceField`.
"""
def default(self, obj):
if isinstance(obj, set):
return list(obj)
return super().default(obj)
So I had a model with one foreign key reference that was working really well for a few weeks. I ended up having to add another foreign key reference to the model and now I'm not able to save any records using a serializer. I should mention I'm using Django 2.1.
Here's the model I'm using (some fields removed for simplicity):
class Finding(models.Model):
finding_id = models.IntegerField(null=False, blank=False, primary_key=True, db_index=True)
name = models.CharField(null=True, blank=True, max_length=255)
web_app = models.ForeignKey(WebApplication, on_delete=models.CASCADE)
q_id = models.ForeignKey(StagingQkb, on_delete=models.CASCADE)
The new FK is the q_id field. This was just a plain int before. I've actually blown away the old table and the new one is still totally empty so I know it's not a problem with the existing data (the tables with the foreign keys are still intact). When saving Findings before, I would just give the PK of the WebApplication object for 'web_app'. As far as I can tell this is still working. The 'q_id' field, when inserted the same way, complains that it needs an int/string/bytes instead of a StagingQkb object. Well, I'm not giving it a StagingQkb object so what gives!
Here's the serializer:
class FindingSerializer(serializers.ModelSerializer):
class Meta:
model = Finding
fields = '__all__'
The data I'm feeding to the serializer looks like this:
data = {'finding_id': 5514989,
'name': 'Sample-Name',
'q_id': 12345,
'web_app': 67890}
When I insert the data into the serializer I'm doing the following:
>>> fs = FindingSerializer(data=data)
>>> fs.is_valid()
True
>>> fs.save()
The error I'm getting after running the above code looks like this:
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/opt/oss/python35/lib/python3.5/site-packages/rest_framework/serializers.py", line 214, in save
self.instance = self.create(validated_data)
File "/opt/oss/python35/lib/python3.5/site-packages/rest_framework/serializers.py", line 959, in create
raise TypeError(msg)
TypeError: Got a `TypeError` when calling `Finding.objects.create()`. This may be because you have a writable field on the serializer class that is not a valid argument to `Finding.objects.create()`. You may need to make the field read-only, or override the FindingSerializer.create() method to handle this correctly.
Original exception was:
Traceback (most recent call last):
File "/opt/oss/python35/lib/python3.5/site-packages/rest_framework/serializers.py", line 940, in create
instance = ModelClass._default_manager.create(**validated_data)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/query.py", line 413, in create
obj.save(force_insert=True, using=self.db)
File "/home/dpz3w0q/AutonomousPrimeD/autonomousprimed/Finding/models.py", line 83, in save
q_id=self.q_id)
File "/home/dpz3w0q/AutonomousPrimeD/autonomousprimed/Finding/models.py", line 173, in evaluate
if ScoreMatrix.objects.filter(q_id=q_id).count() > 0:
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/query.py", line 844, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/query.py", line 862, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1263, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1287, in _add_q
split_subq=split_subq,
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1225, in build_filter
condition = self.build_lookup(lookups, col, value)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1096, in build_lookup
lookup = lookup_class(lhs, rhs)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/lookups.py", line 20, in __init__
self.rhs = self.get_prep_lookup()
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/lookups.py", line 70, in get_prep_lookup
return self.lhs.output_field.get_prep_value(self.rhs)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/fields/__init__.py", line 1807, in get_prep_value
return int(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'StagingQkb'
I'm completely stuck here. I haven't changed the way I'm passing data to the serializer, so I really can't tell what I've done wrong. If anyone is able to help me work through this I'd really appreciate it!
Thanks to #WillKeeling I realized that I had a reference to Finding.q_id in my save() method that I forgot to update after making the FK changes. The PK of the foreign table is qkb_id, so I changed the reference to Finding.q_id.qkb_id and I was able to save the model.
I've got a front-end that sends JSON to the back-end to switch the input of a digital audio stream, with an optional time component to schedule the switch for the future. Here are the components of making this work:
from views.py:
class SwitchStreamView(views.APIView):
"""
A custom endpoint for switching inputs of radio streams
"""
queryset = RadioStream.objects.all()
def post(self, request, format=None):
serializer = serializers.RadioSwitchSerializer(data=request.data, many=True)
serializer.is_valid()
for stream in serializer.data:
if stream.schedule_time is None:
tasks.switch_stream(stream.mnemonic, stream.current_input)
else:
tasks.schedule_switch(stream.mnemonic, stream.current_input, stream.schedule_time)
return HttpResponse('')
from serializers.py:
class RadioSwitchSerializer(serializers.ModelSerializer):
schedule_time = serializers.SerializerMethodField()
def get_schedule_time(self, obj):
return obj.get('schedule_time', None)
class Meta:
model = RadioStream
fields = ('mnemonic', 'current_input', 'schedule_time')
The issue I'm having is that however I try and send a test JSON snippet, I'm getting errors. With this setup, sending
[
{
"mnemonic": "TEST",
"current_input": "TEST"
}
]
results in the error 'str' object has no attribute 'pk', but if I change RadioSwitchSerializer(data=request.data, many=True) to many=False, and send
{
"mnemonic": "TEST",
"current_input": "TEST"
}
I get the response 'str' object has no attribute 'schedule_time' instead.
My plan was to use mnemonic to identify the stream, and current_input to identify which input to switch it to. My questions are; Why is this not working, and should I be using a non-Model serializer for this custom action instead of trying to fit the action into the existing fields of the model?
Edit: Here is the traceback
Internal Server Error: /api/switch/
Traceback (most recent call last):
File "...\lib\site-packages\django\core\handlers\exception.py", line 35, in inner
response = get_response(request)
File "...\lib\site-packages\django\core\handlers\base.py", line 128, in _get_response
response = self.process_exception_by_middleware(e, request)
File "...\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "...\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "...\lib\site-packages\django\views\generic\base.py", line 69, in view
return self.dispatch(request, *args, **kwargs)
File "...\lib\site-packages\rest_framework\views.py", line 489, in dispatch
response = self.handle_exception(exc)
File "...\lib\site-packages\rest_framework\views.py", line 449, in handle_exception
self.raise_uncaught_exception(exc)
File "...\lib\site-packages\rest_framework\views.py", line 486, in dispatch
response = handler(request, *args, **kwargs)
File "...\radio_switching\views.py", line 45, in post
for stream in serializer.data:
File "...\lib\site-packages\rest_framework\serializers.py", line 738, in data
ret = super(ListSerializer, self).data
File "...\lib\site-packages\rest_framework\serializers.py", line 266, in data
self._data = self.get_initial()
File "...\lib\site-packages\rest_framework\serializers.py", line 573, in get_initial
return self.to_representation(self.initial_data)
File "...\lib\site-packages\rest_framework\serializers.py", line 656, in to_representation
self.child.to_representation(item) for item in iterable
File "...\lib\site-packages\rest_framework\serializers.py", line 656, in <listcomp>
self.child.to_representation(item) for item in iterable
File "...\lib\site-packages\rest_framework\serializers.py", line 500, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "...\lib\site-packages\rest_framework\relations.py", line 259, in to_representation
return value.pk
AttributeError: 'str' object has no attribute 'pk'
replace your views.py by this snippet,
class SwitchStreamView(views.APIView):
"""
A custom endpoint for switching inputs of radio streams
"""
queryset = RadioStream.objects.all()
def post(self, request, format=None):
serializer = serializers.RadioSwitchSerializer(data=request.data, many=True)
serializer.is_valid()
for stream in serializer.data:
if 'schedule_time' not in stream:
tasks.switch_stream(stream['mnemonic'], stream['current_input'])
else:
tasks.schedule_switch(stream['mnemonic'], stream['current_input'], stream['schedule_time'])
return HttpResponse('')
The reason for the error is, you are trying to access a python dict using dot operator. To access dictionary elements, you can use the familiar square brackets along with the key to obtaining it's value. Here is the official doc
EDIT
AttributeError: 'str' object has no attribute 'pk' this error because, somewhere you trying to access .pk from a str object
Reproducing the error
In [7]: my_str = 'this is just a string'
In [8]: my_str.pk
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-8-5bc39c990550> in <module>()
----> 1 my_str.pk
AttributeError: 'str' object has no attribute 'pk'
There were a few issues, but it turns out the root issue was that serlializer.data was for whatever reason returning a string and not an array of objects. I ended up replacing the ModelSerializer with a regular Serializer here:
class RadioSwitchSerializer(serializers.Serializer):
mnemonic = serializers.CharField(max_length=20)
new_input = serializers.CharField(max_length=20)
schedule_time = serializers.DateTimeField(allow_null=True)
As per Jerin's answer, I also fixed up the lines accessing the stream dictionary to use square brackets rather than the dot operator. These two things have fixed the issue.
I have written a unit test to test an api....Its a GET call....
When I run it , i get this error ...Heres the traceback....
Traceback (most recent call last):
File "/home/arindam31/XXX-Name/mapi/tests.py", line 141, in test_get_cities
response = self.cl.get('/mapi/latest/cities/')
File "/usr/local/lib/python2.7/dist-packages/django/test/client.py", line 445, in get
response = super(Client, self).get(path, data=data, **extra)
File "/usr/local/lib/python2.7/dist-packages/django/test/client.py", line 229, in get
return self.request(**r)
File "/usr/local/lib/python2.7/dist-packages/django/test/client.py", line 387, in request
response = self.handler(environ)
File "/usr/local/lib/python2.7/dist-packages/django/test/client.py", line 84, in __call__
response = self.get_response(request)
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 169, in get_response
response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 218, in handle_uncaught_exception
return callback(request, **param_dict)
File "/home/arindam31/XXX-Name/saul/views.py", line 546, in do_handle_500
return render_to_response("500.html", context_instance=RequestContext(request))
File "/usr/local/lib/python2.7/dist-packages/django/template/context.py", line 177, in __init__
self.update(processor(request))
File "/home/arindam31/XXX-Name/saul/context_processors.py", line 46, in common_context
ret_dict['city'] = request.city
AttributeError: 'WSGIRequest' object has no attribute 'city'
Heres my unit test...
def test_get_cities(self):
request = HttpRequest()
request.city = self.c1
response = self.cl.get('/mapi/latest/cities/')
content = response.content
data = json.loads(content)
for city in City.objects.all():
assert city.name in data
assert data[city.name] == city.pk
Here , self.c1 is a city type object in the setUp part....HttpRequest is from django.http.
The view being tested is below:
def get_cities(request):
print "1"
if ENABLE_HTTPS_CHECK and not request.is_secure():
return HttpResponseForbidden()
if request.method != 'GET':
return HttpResponseNotAllowed('Not allowed')
city_map = _get_city_map()
response = HttpResponse(json.dumps(city_map)
content_type='application/json')
response['Cache-Control'] = 'no-cache'
return response
If you want to test your view with your own request object, you should call the view directly. You should use the RequestFactory to create your request.
As Daniel Roseman points out your request object having a city attribute remains broken, unless you have some middleware that would set it. You clearly have some middleware that require it to be set in saul/context_processors.py.
Using RequestFactory and calling the view directly circumvents the middleware entirely, so you can concentrate on testing your view (if the view supports the absent middleware).
If your view requires the middelware to be operational, you probably just need to be logged in using the test client. It has a session pr test method.
I have no idea what you are trying to do here. You instantiate a request object, assign a city attribute, then proceed to ignore that object and just use the standard test client. I don't know why you would think that that request would be used for the client get.
To be honest though I think that your entire design is broken. You don't show how you expect to get the parameter into the request in a normal non-test scenario, but usually you would pass it via the POST or GET parameters rather than annotating it into the request somehow. That would of course make it easier to test, since you could just pass the dictionary to the client call.