No to gdzieś coś jest źle, bo metoda pop
w tym miejscu odnosi się do słownika i validated_data
powinno być słownikiem. Gdzieś coś musi być źle przypisane albo zadeklarowane.
- 1
- 2

- Rejestracja:prawie 5 lat
- Ostatnio:około 18 godzin
- Lokalizacja:Wrocław
- Postów:498

- Rejestracja:prawie 15 lat
- Ostatnio:około 10 godzin
- Lokalizacja:Laska, z Polski
- Postów:10056
szafran98 napisał(a):
No to gdzieś coś jest źle, bo metoda
pop
w tym miejscu odnosi się do słownika ivalidated_data
powinno być słownikiem. Gdzieś coś musi być źle przypisane albo zadeklarowane.
Gość nadpisał create()
w widoku, a create()
dostaje request, nie dict
. To że próbuje go użyć jak słownika to inna sprawa.


- Rejestracja:prawie 5 lat
- Ostatnio:około 18 godzin
- Lokalizacja:Wrocław
- Postów:498
Tak jak @Riddle napisał, metoda create
ma być nadpisana w serializerze. Sam dałeś link do dokumentacji, a źle z niej przepisałeś XD
class UserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer()
class Meta:
model = User
fields = ['username', 'email', 'profile']
def create(self, validated_data):
profile_data = validated_data.pop('profile')
user = User.objects.create(**validated_data)
Profile.objects.create(user=user, **profile_data)
return user

- Rejestracja:ponad 2 lata
- Ostatnio:około miesiąc
- Postów:119
Nadpisalem Create w serializerze i teraz wysyłam w POSTMANIE następujący json na widok:
{
"invoice_num": "faktura 12-2022",
"issuer": "IT Company, address, NIP 424234242",
"header": "COmpany name, address, NIP 332423324",
"notes": "Split payment",
"lines": [
{
"name": "uslugi programistyczne",
"net": 1000,
"tax": 22
},
{
"name": "hosting",
"net": 200,
"tax": 22
}
]
}
i otrzymuje błąd:
TypeError at /endpoint/
django.db.models.manager.BaseManager._get_queryset_methods.<locals>.create_method.<locals>.manager_method() argument after ** must be a mapping, not list
print(validated_data)
zwraca teraz:
{'invoice_num': 'faktura 12-2022', 'issuer': 'IT Company, address, NIP 424234242', 'header': 'COmpany name, address, NIP 332423324', 'notes': 'Split payment', 'lines': [OrderedDict([('name', 'uslugi programistyczne'), ('net', 1000), ('tax', 22)]), OrderedDict([('name', 'hosting'), ('net', 200), ('tax', 22)])]}

- Rejestracja:prawie 5 lat
- Ostatnio:około 18 godzin
- Lokalizacja:Wrocław
- Postów:498
No to musisz debugować. Coś w metodzie create
. Możliwe, że przekazujesz listę lines
, a nie zmapowane instancje modelu. W docsach masz:
def create(self, validated_data):
tracks_data = validated_data.pop('tracks')
album = Album.objects.create(**validated_data)
for track_data in tracks_data:
Track.objects.create(album=album, **track_data)
return album
Zagnieżdżona relacja many-to-one jest tworzona w pętli. W metodzie create
, którą wkleiłeś nie ma pętli.

- Rejestracja:ponad 2 lata
- Ostatnio:około miesiąc
- Postów:119
Teraz działa jak zrobiłem na podstawie tego kodu co mi wysłałeś. Szafran i RIddle macie u mnie browara.
ale nadal nie wiem jak wyprintowac na dokumencie PDF zagnieżdżony słownik lines. Próbuje:
lines = [[x['name'] for x in y['lines']] for y in request.data]
for line in lines:
textob.textLine(line)
dostaje error:
string indices must be integers
print(request.data['lines'])
zwraca:
[{'name': 'uslugi programistyczne', 'net': 3000, 'tax': 22}, {'name': 'hosting', 'net': 400, 'tax': 22}]

- Rejestracja:prawie 5 lat
- Ostatnio:około 18 godzin
- Lokalizacja:Wrocław
- Postów:498
No brawo, zaraz podeślę adres na pw. XD
Dodatkowo jeśli to nie jest zdanie na studia, tylko faktycznie się tego uczysz, to weź podszkol się z czystego Django i Pythona. Django narzuca architekturę i udostępnia programiście API, ale dużo rzeczy dzieje się tam pod spodem i trzeba mieć wyobrażenie co tam się po kolei robi, bo inaczej ciężko o modyfikacje.

- Rejestracja:prawie 5 lat
- Ostatnio:około 18 godzin
- Lokalizacja:Wrocław
- Postów:498
Naprawiłeś? XD

- Rejestracja:ponad 2 lata
- Ostatnio:około miesiąc
- Postów:119
tego słownika nie moge wyprintować.
print(request.data['lines'])
zwraca: [{'name': 'uslugi programistyczne', 'net': 3000, 'tax': 22}, {'name': 'hosting', 'net': 400, 'tax': 22}]

- Rejestracja:prawie 5 lat
- Ostatnio:około 18 godzin
- Lokalizacja:Wrocław
- Postów:498
No i tak miało być przecież. To zamień lines = [x['name'] for x in main_dict['lines']]

- Rejestracja:ponad 2 lata
- Ostatnio:około miesiąc
- Postów:119
super. Tylko teraz mi printuje
lines:
uslugi programistyczne
hosting
a to ma być faktura czyli nie tylko nazwa uslugi ale tez koszt i podatek czyli:
Lines:
-
usługi programistyczne - kwota - podatek
-
hosting - kwota - podatek
teraz mam kod taki:
lines = [x['name'] for x in request.data['lines']] for line in lines: textob.textLine('-------------------------------------------------------------------------------------' '-------------') textob.textLine(line)
efekt taki:
invoice num: faktura 12/2022
issuer: IT Company, address, NIP 424234242
header: COmpany name, address, NIP 332423324
notes: Split payment
--------------------------------------------------------------------------------------------------
uslugi programistyczne
--------------------------------------------------------------------------------------------------
hosting
- Zrzut ekranu z 2022-12-19 14-34-28.png (28 KB) - ściągnięć: 7

- Rejestracja:prawie 5 lat
- Ostatnio:około 18 godzin
- Lokalizacja:Wrocław
- Postów:498
No to już są proste operacje na słowniku.
Tutaj jak posługiwać się tą strukturą danych: https://realpython.com/python-dicts/
A tutaj o f-stringach poczytaj: https://realpython.com/python-f-strings/

- Rejestracja:ponad 2 lata
- Ostatnio:około miesiąc
- Postów:119
Nie ma rozwiązania w tym co mi wysłałeś. Muszę poszukać w internecie

- Rejestracja:prawie 5 lat
- Ostatnio:około 18 godzin
- Lokalizacja:Wrocław
- Postów:498
I nie będzie rozwiązania w internecie. Przecież nie znajdziesz przykładu, gdzie ktoś robi to samo z takimi samymi danymi. To Ty masz je wymyślić, a do tego musisz zrozumieć to co wysłałem w ostatnim poście. Żeby wypisywało to co chcesz, to jest jedna, maks dwie linijki kodu. Iteracje po lines już masz, więć musisz tylko wyciągnąć dane ze słownika.

- Rejestracja:ponad 2 lata
- Ostatnio:około miesiąc
- Postów:119
Wiem, że nie znajdę takiego samego przykładu ale mogę analogicznie zrobić do jakiegoś przykładu.
Proszę pomóż mi z tym bo męczę się i nie mogę sobie poradzić.

- Rejestracja:prawie 5 lat
- Ostatnio:około 18 godzin
- Lokalizacja:Wrocław
- Postów:498
Wariacie musisz tylko zmienić list comprehension, które Ci podałem XD
lines = [x['name'] for x in request.data['lines']]
Wiesz co znaczy operacja po prawej stronie działania? Zwróć wartość dla klucza name
od x dla każdego x z listy, która znajduje się w słowniku request.data
pod kluczem lines
.
Teraz popatrz na to:
name = 'programowanie'
net = 15000
tax = 19
invoice_service = f'{name} - {net} - {tax}'
print(invoice_service) -> programowanie - 15000 - 19
Prawda, że proste?
W tym: lines = [x['name'] for x in request.data['lines']]
, to co zwracasz dla każdego elementu, w tym przypadku x['name']
może być czymkolwiek. Stringiem, intem, boolem, funkcją, słownikiem, listą, krotką, klasą, obiektem i bóg wie czym jeszcze. W tym poście jest wszystko czego potrzebujesz. To jest ten przykład, który chciałeś szukać na necie.

- Rejestracja:ponad 2 lata
- Ostatnio:około miesiąc
- Postów:119
name = 'programowanie'
net = 15000
tax = 19
invoice_service = f'{name} - {net} - {tax}'
print(invoice_service) -> programowanie - 15000 - 19
no to jest proste. to też rozumiem
lines = [x['name'] for x in request.data['lines']]
ale nadal nie rozumiem jak stworzyć tą pętle, która będzie printowała kolejno name, net, tax. No bo przecież nie tak:
lines = [x['name'], y['net'], c['tax'] for x, y ,c in request.data['lines']]

- Rejestracja:prawie 15 lat
- Ostatnio:około 10 godzin
- Lokalizacja:Laska, z Polski
- Postów:10056
hubertsuder napisał(a):
ale nadal nie rozumiem jak stworzyć tą pętle, która będzie printowała kolejno name, net, tax. No bo przecież nie tak:
lines = [x['name'], y['net'], c['tax'] for x, y ,c in request.data['lines']]
To Ci zwróci tuple
z trzema wartościami. Możesz zrobić na całości print(lines)
i zobaczyć co tam siedzi.
Jeśli chcesz najpierw wszystkie 'name'
, potem wszystkie 'net'
, etc. to możesz zrobić tak:
print([x['name'] for x in request.data['lines']])
print([x['net'] for x in request.data['lines']])
print([x['tax'] for x in request.data['lines']])

- Rejestracja:prawie 5 lat
- Ostatnio:około 18 godzin
- Lokalizacja:Wrocław
- Postów:498
Przecież możesz zwrócić stringa [f"{x['name']} - {x['net']} - {x['tax']}" for x in request.data['lines']]



- Rejestracja:ponad 2 lata
- Ostatnio:około miesiąc
- Postów:119
lines = [f"x['name'] - x['net'] - x['tax']" for x in request.data['lines']]
for line in lines:
textob.textLine('-------------------------------------------------------------------------------------'
'-------------')
textob.textLine(line)
zwraca:
--------------------------------------------------------------------------------------------------
x['name'] - x['net'] - x['tax']
--------------------------------------------------------------------------------------------------
x['name'] - x['net'] - x['tax']

x['name']
owrapuj w {}
, zapomniałem


- Rejestracja:ponad 2 lata
- Ostatnio:około miesiąc
- Postów:119
No teraz śmiga dobrze. Działa wszystko. Tylko nadal nie wyglada to dobrze na fakturze. Macie jakis pomysl zeby to wizualnie poprawic?
I jeszcze chcialem, żeby zliczało wszystkie x['net'] w sume kwoty do zapłacenia.
--------------------------------------------------------------------------------------------------
uslugi programistyczne - 1000 - 22
--------------------------------------------------------------------------------------------------
hosting - 200 - 22

- Rejestracja:prawie 5 lat
- Ostatnio:około 18 godzin
- Lokalizacja:Wrocław
- Postów:498
Jak ma być ładniej? To zwykłe formatowanie stringów. Sumowanie net w pętli najprościej i będziesz miał spokój. Tak samo analogicznie. Masz przykłady w temacie albo na necie znajdziesz, zresztą pętle, to są chyba na 30 stronie książki z podstawami. Chyba wyniosłeś jakąś wiedzę przez te pięć stron tematu.

- Rejestracja:ponad 2 lata
- Ostatnio:około miesiąc
- Postów:119
dobra, jest dobrze. Dziekuje CI Szafran. Chciałbym CI sie jakoś odwdzieczyc

- Rejestracja:prawie 5 lat
- Ostatnio:około 18 godzin
- Lokalizacja:Wrocław
- Postów:498
Nie trzeba. Po prostu to są takie podstawowe rzeczy, że z mojej perspektywy masz totalny brak talentu do tego albo w dupie naukę. Nie chcę Cię posądzać, że nie masz umiejętności, żeby to ogarnąć, więc bardziej zakładam, że nie chcesz tego zrozumieć. Triggeruje mnie takie podejście, bo zawsze na koniec semestru pojawiają się tutaj studenciaki, którzy udają, że mają problem z czymś, a koniec końców chcą gotowca albo po prostu wklejają treść zadania i proszą o rozwiazanie. Parę dni temu był tu taki, to jeszcze bezczelnie pytał, czemu go pouczam, a nie po prostu dam gotowca XD
Nie chcę generalizować, są też tacy, którzy faktycznie próbują, ale czegoś nie wiedzą i takim z chęcią pomogę.
Jak chcesz mieć szybko rozwiązanie i programowanie Cię w ogóle nie interesuje, to wtedy tworzysz temat w dziale "Ogłoszenia drobne" i zaoszczędzisz czas, swój i kogoś. Jeśli faktycznie próbujesz coś sam zrobić i nie możesz znaleźć rozwiązanie, to na pewno ktoś Ci pomoże.



- Rejestracja:ponad 2 lata
- Ostatnio:około miesiąc
- Postów:119
Szafran podałeś mi dobre rozwiazanie:
lines = [f"{x['name']} - net pay: {x['net']} zl - tax: {x['tax']} %" for x in request.data['lines']]
for line in lines:
textob.textLine('-------------------------------------------------------------------------------------'
'-------------')
textob.textLine(line)
Tylko że w pętli line in lines
nie moge się odwoływać do zmiennych wtedy. I nie moge zsumować kwoty brutto, czyli wymnożyć 2 zmienne, x['net'] x x['tax']. Udało mi się tylko z kwotą netto:
lines_net = [x['net'] for x in request.data['lines']]
net_pay = 0
for line in lines_net:
net_pay += line

- Rejestracja:prawie 5 lat
- Ostatnio:około 18 godzin
- Lokalizacja:Wrocław
- Postów:498
Jak dla każdej lini chcesz zwrócić kwotę netto i brutto, to zrób tak:
def remap_lines_dict(line):
line.update(
{'gross_ammount': line['net'] * float(f"1.{line['tax']}")})
return line
lines = [remap_lines_dict(line) for line in dict['lines']]
Nie jest 1:1 jak Ty napisałeś, bo nie mam czasu teraz rozkminiać. Masz listę i na stringi już sobie zmapujesz.

- Rejestracja:ponad 2 lata
- Ostatnio:około miesiąc
- Postów:119
nic mi nie printuje jak robie tak jak mówisz. Po prostu puste na pdf

- Rejestracja:prawie 5 lat
- Ostatnio:około 18 godzin
- Lokalizacja:Wrocław
- Postów:498
A co jest w lines?

- Rejestracja:ponad 2 lata
- Ostatnio:około miesiąc
- Postów:119
[None, None]
- 1
- 2